mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-24 19:26:39 +00:00
Compare commits
41 Commits
debug-user
...
feature/fl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cccc615783 | ||
|
|
2021463ca0 | ||
|
|
f48cfd52e9 | ||
|
|
6838f53f40 | ||
|
|
8276236dfa | ||
|
|
994b923d56 | ||
|
|
59e2432231 | ||
|
|
eee0d123e4 | ||
|
|
e943203ae2 | ||
|
|
6a775217cf | ||
|
|
175674749f | ||
|
|
1e534cecf6 | ||
|
|
aa3aa8c6a8 | ||
|
|
fbdfe45c25 | ||
|
|
81ee172db8 | ||
|
|
f8fd65a65f | ||
|
|
62b978c050 | ||
|
|
4ebf1410c6 | ||
|
|
630edf2480 | ||
|
|
ea469d28d7 | ||
|
|
597f1d47b8 | ||
|
|
fcc96417f9 | ||
|
|
8755211a60 | ||
|
|
e6d4653b08 | ||
|
|
eb69f2de78 | ||
|
|
206420c085 | ||
|
|
88a864c195 | ||
|
|
a789e9e6d8 | ||
|
|
9930913e4e | ||
|
|
48675f579f | ||
|
|
afec455f86 | ||
|
|
035c5d9f23 | ||
|
|
b2a5b29fb2 | ||
|
|
9ec61206c2 | ||
|
|
1b011a2d85 | ||
|
|
a85ea1ddb0 | ||
|
|
829e40d2aa | ||
|
|
6344e34880 | ||
|
|
a76ca8c565 | ||
|
|
26693e4ea8 | ||
|
|
f6a71f4193 |
98
client/cmd/forwarding_rules.go
Normal file
98
client/cmd/forwarding_rules.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var forwardingRulesCmd = &cobra.Command{
|
||||||
|
Use: "forwarding",
|
||||||
|
Short: "List forwarding rules",
|
||||||
|
Long: `Commands to list forwarding rules.`,
|
||||||
|
}
|
||||||
|
|
||||||
|
var forwardingRulesListCmd = &cobra.Command{
|
||||||
|
Use: "list",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
|
Short: "List forwarding rules",
|
||||||
|
Example: " netbird forwarding list",
|
||||||
|
Long: "Commands to list forwarding rules.",
|
||||||
|
RunE: listForwardingRules,
|
||||||
|
}
|
||||||
|
|
||||||
|
func listForwardingRules(cmd *cobra.Command, _ []string) error {
|
||||||
|
conn, err := getClient(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
client := proto.NewDaemonServiceClient(conn)
|
||||||
|
resp, err := client.ForwardingRules(cmd.Context(), &proto.EmptyRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to list network: %v", status.Convert(err).Message())
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.GetRules()) == 0 {
|
||||||
|
cmd.Println("No forwarding rules available.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
printForwardingRules(cmd, resp.GetRules())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printForwardingRules(cmd *cobra.Command, rules []*proto.ForwardingRule) {
|
||||||
|
cmd.Println("Available forwarding rules:")
|
||||||
|
|
||||||
|
// Sort rules by translated address
|
||||||
|
sort.Slice(rules, func(i, j int) bool {
|
||||||
|
if rules[i].GetTranslatedAddress() != rules[j].GetTranslatedAddress() {
|
||||||
|
return rules[i].GetTranslatedAddress() < rules[j].GetTranslatedAddress()
|
||||||
|
}
|
||||||
|
if rules[i].GetProtocol() != rules[j].GetProtocol() {
|
||||||
|
return rules[i].GetProtocol() < rules[j].GetProtocol()
|
||||||
|
}
|
||||||
|
|
||||||
|
return getFirstPort(rules[i].GetDestinationPort()) < getFirstPort(rules[j].GetDestinationPort())
|
||||||
|
})
|
||||||
|
|
||||||
|
var lastIP string
|
||||||
|
for _, rule := range rules {
|
||||||
|
dPort := portToString(rule.GetDestinationPort())
|
||||||
|
tPort := portToString(rule.GetTranslatedPort())
|
||||||
|
if lastIP != rule.GetTranslatedAddress() {
|
||||||
|
lastIP = rule.GetTranslatedAddress()
|
||||||
|
cmd.Printf("\nTranslated peer: %s\n", rule.GetTranslatedHostname())
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Printf(" Local %s/%s to %s:%s\n", rule.GetProtocol(), dPort, rule.GetTranslatedAddress(), tPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFirstPort(portInfo *proto.PortInfo) int {
|
||||||
|
switch v := portInfo.PortSelection.(type) {
|
||||||
|
case *proto.PortInfo_Port:
|
||||||
|
return int(v.Port)
|
||||||
|
case *proto.PortInfo_Range_:
|
||||||
|
return int(v.Range.GetStart())
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func portToString(translatedPort *proto.PortInfo) string {
|
||||||
|
switch v := translatedPort.PortSelection.(type) {
|
||||||
|
case *proto.PortInfo_Port:
|
||||||
|
return fmt.Sprintf("%d", v.Port)
|
||||||
|
case *proto.PortInfo_Range_:
|
||||||
|
return fmt.Sprintf("%d-%d", v.Range.GetStart(), v.Range.GetEnd())
|
||||||
|
default:
|
||||||
|
return "No port specified"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -145,6 +145,7 @@ func init() {
|
|||||||
rootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
rootCmd.AddCommand(sshCmd)
|
rootCmd.AddCommand(sshCmd)
|
||||||
rootCmd.AddCommand(networksCMD)
|
rootCmd.AddCommand(networksCMD)
|
||||||
|
rootCmd.AddCommand(forwardingRulesCmd)
|
||||||
rootCmd.AddCommand(debugCmd)
|
rootCmd.AddCommand(debugCmd)
|
||||||
|
|
||||||
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
|
serviceCmd.AddCommand(runCmd, startCmd, stopCmd, restartCmd) // service control commands are subcommands of service
|
||||||
@@ -153,6 +154,8 @@ func init() {
|
|||||||
networksCMD.AddCommand(routesListCmd)
|
networksCMD.AddCommand(routesListCmd)
|
||||||
networksCMD.AddCommand(routesSelectCmd, routesDeselectCmd)
|
networksCMD.AddCommand(routesSelectCmd, routesDeselectCmd)
|
||||||
|
|
||||||
|
forwardingRulesCmd.AddCommand(forwardingRulesListCmd)
|
||||||
|
|
||||||
debugCmd.AddCommand(debugBundleCmd)
|
debugCmd.AddCommand(debugBundleCmd)
|
||||||
debugCmd.AddCommand(logCmd)
|
debugCmd.AddCommand(logCmd)
|
||||||
logCmd.AddCommand(logLevelCmd)
|
logCmd.AddCommand(logLevelCmd)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -89,13 +90,13 @@ func startManagement(t *testing.T, config *mgmt.Config, testFile string) (*grpc.
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, iv, metrics)
|
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, iv, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secretsManager := mgmt.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
secretsManager := mgmt.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
||||||
mgmtServer, err := mgmt.NewServer(context.Background(), config, accountManager, settings.NewManager(store), peersUpdateManager, secretsManager, nil, nil, nil)
|
mgmtServer, err := mgmt.NewServer(context.Background(), config, accountManager, settings.NewManagerMock(), peersUpdateManager, secretsManager, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,8 @@ type entry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type aclManager struct {
|
type aclManager struct {
|
||||||
iptablesClient *iptables.IPTables
|
iptablesClient *iptables.IPTables
|
||||||
wgIface iFaceMapper
|
wgIface iFaceMapper
|
||||||
routingFwChainName string
|
|
||||||
|
|
||||||
entries aclEntries
|
entries aclEntries
|
||||||
optionalEntries map[string][]entry
|
optionalEntries map[string][]entry
|
||||||
ipsetStore *ipsetStore
|
ipsetStore *ipsetStore
|
||||||
@@ -41,12 +39,10 @@ type aclManager struct {
|
|||||||
stateManager *statemanager.Manager
|
stateManager *statemanager.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func newAclManager(iptablesClient *iptables.IPTables, wgIface iFaceMapper, routingFwChainName string) (*aclManager, error) {
|
func newAclManager(iptablesClient *iptables.IPTables, wgIface iFaceMapper) (*aclManager, error) {
|
||||||
m := &aclManager{
|
m := &aclManager{
|
||||||
iptablesClient: iptablesClient,
|
iptablesClient: iptablesClient,
|
||||||
wgIface: wgIface,
|
wgIface: wgIface,
|
||||||
routingFwChainName: routingFwChainName,
|
|
||||||
|
|
||||||
entries: make(map[string][][]string),
|
entries: make(map[string][][]string),
|
||||||
optionalEntries: make(map[string][]entry),
|
optionalEntries: make(map[string][]entry),
|
||||||
ipsetStore: newIpsetStore(),
|
ipsetStore: newIpsetStore(),
|
||||||
@@ -314,9 +310,12 @@ func (m *aclManager) seedInitialEntries() {
|
|||||||
m.appendToEntries("INPUT", []string{"-i", m.wgIface.Name(), "-j", chainNameInputRules})
|
m.appendToEntries("INPUT", []string{"-i", m.wgIface.Name(), "-j", chainNameInputRules})
|
||||||
m.appendToEntries("INPUT", append([]string{"-i", m.wgIface.Name()}, established...))
|
m.appendToEntries("INPUT", append([]string{"-i", m.wgIface.Name()}, established...))
|
||||||
|
|
||||||
|
// Inbound is handled by our ACLs, the rest is dropped.
|
||||||
|
// For outbound we respect the FORWARD policy. However, we need to allow established/related traffic for inbound rules.
|
||||||
m.appendToEntries("FORWARD", []string{"-i", m.wgIface.Name(), "-j", "DROP"})
|
m.appendToEntries("FORWARD", []string{"-i", m.wgIface.Name(), "-j", "DROP"})
|
||||||
m.appendToEntries("FORWARD", []string{"-i", m.wgIface.Name(), "-j", m.routingFwChainName})
|
|
||||||
m.appendToEntries("FORWARD", append([]string{"-o", m.wgIface.Name()}, established...))
|
m.appendToEntries("FORWARD", []string{"-o", m.wgIface.Name(), "-j", chainRTFWDOUT})
|
||||||
|
m.appendToEntries("FORWARD", []string{"-i", m.wgIface.Name(), "-j", chainRTFWDIN})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *aclManager) seedInitialOptionalEntries() {
|
func (m *aclManager) seedInitialOptionalEntries() {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func Create(wgIface iFaceMapper) (*Manager, error) {
|
|||||||
return nil, fmt.Errorf("create router: %w", err)
|
return nil, fmt.Errorf("create router: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.aclMgr, err = newAclManager(iptablesClient, wgIface, chainRTFWD)
|
m.aclMgr, err = newAclManager(iptablesClient, wgIface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create acl manager: %w", err)
|
return nil, fmt.Errorf("create acl manager: %w", err)
|
||||||
}
|
}
|
||||||
@@ -226,6 +226,22 @@ func (m *Manager) DisableRouting() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddDNATRule adds a DNAT rule
|
||||||
|
func (m *Manager) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.router.AddDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDNATRule deletes a DNAT rule
|
||||||
|
func (m *Manager) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.router.DeleteDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
func getConntrackEstablished() []string {
|
func getConntrackEstablished() []string {
|
||||||
return []string{"-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
|
return []string{"-m", "conntrack", "--ctstate", "RELATED,ESTABLISHED", "-j", "ACCEPT"}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import (
|
|||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/internal/acl/id"
|
"github.com/netbirdio/netbird/client/internal/acl/id"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/routemanager/ipfwdstate"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
||||||
"github.com/netbirdio/netbird/client/internal/statemanager"
|
"github.com/netbirdio/netbird/client/internal/statemanager"
|
||||||
nbnet "github.com/netbirdio/netbird/util/net"
|
nbnet "github.com/netbirdio/netbird/util/net"
|
||||||
@@ -23,22 +24,36 @@ import (
|
|||||||
|
|
||||||
// constants needed to manage and create iptable rules
|
// constants needed to manage and create iptable rules
|
||||||
const (
|
const (
|
||||||
tableFilter = "filter"
|
tableFilter = "filter"
|
||||||
tableNat = "nat"
|
tableNat = "nat"
|
||||||
tableMangle = "mangle"
|
tableMangle = "mangle"
|
||||||
|
|
||||||
chainPOSTROUTING = "POSTROUTING"
|
chainPOSTROUTING = "POSTROUTING"
|
||||||
chainPREROUTING = "PREROUTING"
|
chainPREROUTING = "PREROUTING"
|
||||||
chainRTNAT = "NETBIRD-RT-NAT"
|
chainRTNAT = "NETBIRD-RT-NAT"
|
||||||
chainRTFWD = "NETBIRD-RT-FWD"
|
chainRTFWDIN = "NETBIRD-RT-FWD-IN"
|
||||||
|
chainRTFWDOUT = "NETBIRD-RT-FWD-OUT"
|
||||||
chainRTPRE = "NETBIRD-RT-PRE"
|
chainRTPRE = "NETBIRD-RT-PRE"
|
||||||
|
chainRTRDR = "NETBIRD-RT-RDR"
|
||||||
routingFinalForwardJump = "ACCEPT"
|
routingFinalForwardJump = "ACCEPT"
|
||||||
routingFinalNatJump = "MASQUERADE"
|
routingFinalNatJump = "MASQUERADE"
|
||||||
|
|
||||||
jumpPre = "jump-pre"
|
jumpManglePre = "jump-mangle-pre"
|
||||||
jumpNat = "jump-nat"
|
jumpNatPre = "jump-nat-pre"
|
||||||
matchSet = "--match-set"
|
jumpNatPost = "jump-nat-post"
|
||||||
|
matchSet = "--match-set"
|
||||||
|
|
||||||
|
dnatSuffix = "_dnat"
|
||||||
|
snatSuffix = "_snat"
|
||||||
|
fwdSuffix = "_fwd"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ruleInfo struct {
|
||||||
|
chain string
|
||||||
|
table string
|
||||||
|
rule []string
|
||||||
|
}
|
||||||
|
|
||||||
type routeFilteringRuleParams struct {
|
type routeFilteringRuleParams struct {
|
||||||
Sources []netip.Prefix
|
Sources []netip.Prefix
|
||||||
Destination netip.Prefix
|
Destination netip.Prefix
|
||||||
@@ -62,6 +77,7 @@ type router struct {
|
|||||||
legacyManagement bool
|
legacyManagement bool
|
||||||
|
|
||||||
stateManager *statemanager.Manager
|
stateManager *statemanager.Manager
|
||||||
|
ipFwdState *ipfwdstate.IPForwardingState
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRouter(iptablesClient *iptables.IPTables, wgIface iFaceMapper) (*router, error) {
|
func newRouter(iptablesClient *iptables.IPTables, wgIface iFaceMapper) (*router, error) {
|
||||||
@@ -69,6 +85,7 @@ func newRouter(iptablesClient *iptables.IPTables, wgIface iFaceMapper) (*router,
|
|||||||
iptablesClient: iptablesClient,
|
iptablesClient: iptablesClient,
|
||||||
rules: make(map[string][]string),
|
rules: make(map[string][]string),
|
||||||
wgIface: wgIface,
|
wgIface: wgIface,
|
||||||
|
ipFwdState: ipfwdstate.NewIPForwardingState(),
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ipsetCounter = refcounter.New(
|
r.ipsetCounter = refcounter.New(
|
||||||
@@ -139,9 +156,9 @@ func (r *router) AddRouteFiltering(
|
|||||||
var err error
|
var err error
|
||||||
if action == firewall.ActionDrop {
|
if action == firewall.ActionDrop {
|
||||||
// after the established rule
|
// after the established rule
|
||||||
err = r.iptablesClient.Insert(tableFilter, chainRTFWD, 2, rule...)
|
err = r.iptablesClient.Insert(tableFilter, chainRTFWDIN, 2, rule...)
|
||||||
} else {
|
} else {
|
||||||
err = r.iptablesClient.Append(tableFilter, chainRTFWD, rule...)
|
err = r.iptablesClient.Append(tableFilter, chainRTFWDIN, rule...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -156,12 +173,12 @@ func (r *router) AddRouteFiltering(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *router) DeleteRouteRule(rule firewall.Rule) error {
|
func (r *router) DeleteRouteRule(rule firewall.Rule) error {
|
||||||
ruleKey := rule.GetRuleID()
|
ruleKey := rule.ID()
|
||||||
|
|
||||||
if rule, exists := r.rules[ruleKey]; exists {
|
if rule, exists := r.rules[ruleKey]; exists {
|
||||||
setName := r.findSetNameInRule(rule)
|
setName := r.findSetNameInRule(rule)
|
||||||
|
|
||||||
if err := r.iptablesClient.Delete(tableFilter, chainRTFWD, rule...); err != nil {
|
if err := r.iptablesClient.Delete(tableFilter, chainRTFWDIN, rule...); err != nil {
|
||||||
return fmt.Errorf("delete route rule: %v", err)
|
return fmt.Errorf("delete route rule: %v", err)
|
||||||
}
|
}
|
||||||
delete(r.rules, ruleKey)
|
delete(r.rules, ruleKey)
|
||||||
@@ -212,6 +229,10 @@ func (r *router) deleteIpSet(setName string) error {
|
|||||||
|
|
||||||
// AddNatRule inserts an iptables rule pair into the nat chain
|
// AddNatRule inserts an iptables rule pair into the nat chain
|
||||||
func (r *router) AddNatRule(pair firewall.RouterPair) error {
|
func (r *router) AddNatRule(pair firewall.RouterPair) error {
|
||||||
|
if err := r.ipFwdState.RequestForwarding(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if r.legacyManagement {
|
if r.legacyManagement {
|
||||||
log.Warnf("This peer is connected to a NetBird Management service with an older version. Allowing all traffic for %s", pair.Destination)
|
log.Warnf("This peer is connected to a NetBird Management service with an older version. Allowing all traffic for %s", pair.Destination)
|
||||||
if err := r.addLegacyRouteRule(pair); err != nil {
|
if err := r.addLegacyRouteRule(pair); err != nil {
|
||||||
@@ -238,6 +259,10 @@ func (r *router) AddNatRule(pair firewall.RouterPair) error {
|
|||||||
|
|
||||||
// RemoveNatRule removes an iptables rule pair from forwarding and nat chains
|
// RemoveNatRule removes an iptables rule pair from forwarding and nat chains
|
||||||
func (r *router) RemoveNatRule(pair firewall.RouterPair) error {
|
func (r *router) RemoveNatRule(pair firewall.RouterPair) error {
|
||||||
|
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
|
||||||
|
log.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := r.removeNatRule(pair); err != nil {
|
if err := r.removeNatRule(pair); err != nil {
|
||||||
return fmt.Errorf("remove nat rule: %w", err)
|
return fmt.Errorf("remove nat rule: %w", err)
|
||||||
}
|
}
|
||||||
@@ -264,7 +289,7 @@ func (r *router) addLegacyRouteRule(pair firewall.RouterPair) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rule := []string{"-s", pair.Source.String(), "-d", pair.Destination.String(), "-j", routingFinalForwardJump}
|
rule := []string{"-s", pair.Source.String(), "-d", pair.Destination.String(), "-j", routingFinalForwardJump}
|
||||||
if err := r.iptablesClient.Append(tableFilter, chainRTFWD, rule...); err != nil {
|
if err := r.iptablesClient.Append(tableFilter, chainRTFWDIN, rule...); err != nil {
|
||||||
return fmt.Errorf("add legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
|
return fmt.Errorf("add legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +302,7 @@ func (r *router) removeLegacyRouteRule(pair firewall.RouterPair) error {
|
|||||||
ruleKey := firewall.GenKey(firewall.ForwardingFormat, pair)
|
ruleKey := firewall.GenKey(firewall.ForwardingFormat, pair)
|
||||||
|
|
||||||
if rule, exists := r.rules[ruleKey]; exists {
|
if rule, exists := r.rules[ruleKey]; exists {
|
||||||
if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWD, rule...); err != nil {
|
if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWDIN, rule...); err != nil {
|
||||||
return fmt.Errorf("remove legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
|
return fmt.Errorf("remove legacy forwarding rule %s -> %s: %v", pair.Source, pair.Destination, err)
|
||||||
}
|
}
|
||||||
delete(r.rules, ruleKey)
|
delete(r.rules, ruleKey)
|
||||||
@@ -305,7 +330,7 @@ func (r *router) RemoveAllLegacyRouteRules() error {
|
|||||||
if !strings.HasPrefix(k, firewall.ForwardingFormatPrefix) {
|
if !strings.HasPrefix(k, firewall.ForwardingFormatPrefix) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWD, rule...); err != nil {
|
if err := r.iptablesClient.DeleteIfExists(tableFilter, chainRTFWDIN, rule...); err != nil {
|
||||||
merr = multierror.Append(merr, fmt.Errorf("remove legacy forwarding rule: %v", err))
|
merr = multierror.Append(merr, fmt.Errorf("remove legacy forwarding rule: %v", err))
|
||||||
} else {
|
} else {
|
||||||
delete(r.rules, k)
|
delete(r.rules, k)
|
||||||
@@ -343,9 +368,11 @@ func (r *router) cleanUpDefaultForwardRules() error {
|
|||||||
chain string
|
chain string
|
||||||
table string
|
table string
|
||||||
}{
|
}{
|
||||||
{chainRTFWD, tableFilter},
|
{chainRTFWDIN, tableFilter},
|
||||||
{chainRTNAT, tableNat},
|
{chainRTFWDOUT, tableFilter},
|
||||||
{chainRTPRE, tableMangle},
|
{chainRTPRE, tableMangle},
|
||||||
|
{chainRTNAT, tableNat},
|
||||||
|
{chainRTRDR, tableNat},
|
||||||
} {
|
} {
|
||||||
ok, err := r.iptablesClient.ChainExists(chainInfo.table, chainInfo.chain)
|
ok, err := r.iptablesClient.ChainExists(chainInfo.table, chainInfo.chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -365,16 +392,22 @@ func (r *router) createContainers() error {
|
|||||||
chain string
|
chain string
|
||||||
table string
|
table string
|
||||||
}{
|
}{
|
||||||
{chainRTFWD, tableFilter},
|
{chainRTFWDIN, tableFilter},
|
||||||
|
{chainRTFWDOUT, tableFilter},
|
||||||
{chainRTPRE, tableMangle},
|
{chainRTPRE, tableMangle},
|
||||||
{chainRTNAT, tableNat},
|
{chainRTNAT, tableNat},
|
||||||
|
{chainRTRDR, tableNat},
|
||||||
} {
|
} {
|
||||||
if err := r.createAndSetupChain(chainInfo.chain); err != nil {
|
if err := r.iptablesClient.NewChain(chainInfo.table, chainInfo.chain); err != nil {
|
||||||
return fmt.Errorf("create chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
|
return fmt.Errorf("create chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.insertEstablishedRule(chainRTFWD); err != nil {
|
if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
|
||||||
|
return fmt.Errorf("insert established rule: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
|
||||||
return fmt.Errorf("insert established rule: %w", err)
|
return fmt.Errorf("insert established rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,27 +448,6 @@ func (r *router) addPostroutingRules() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *router) createAndSetupChain(chain string) error {
|
|
||||||
table := r.getTableForChain(chain)
|
|
||||||
|
|
||||||
if err := r.iptablesClient.NewChain(table, chain); err != nil {
|
|
||||||
return fmt.Errorf("failed creating chain %s, error: %v", chain, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *router) getTableForChain(chain string) string {
|
|
||||||
switch chain {
|
|
||||||
case chainRTNAT:
|
|
||||||
return tableNat
|
|
||||||
case chainRTPRE:
|
|
||||||
return tableMangle
|
|
||||||
default:
|
|
||||||
return tableFilter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *router) insertEstablishedRule(chain string) error {
|
func (r *router) insertEstablishedRule(chain string) error {
|
||||||
establishedRule := getConntrackEstablished()
|
establishedRule := getConntrackEstablished()
|
||||||
|
|
||||||
@@ -454,28 +466,43 @@ func (r *router) addJumpRules() error {
|
|||||||
// Jump to NAT chain
|
// Jump to NAT chain
|
||||||
natRule := []string{"-j", chainRTNAT}
|
natRule := []string{"-j", chainRTNAT}
|
||||||
if err := r.iptablesClient.Insert(tableNat, chainPOSTROUTING, 1, natRule...); err != nil {
|
if err := r.iptablesClient.Insert(tableNat, chainPOSTROUTING, 1, natRule...); err != nil {
|
||||||
return fmt.Errorf("add nat jump rule: %v", err)
|
return fmt.Errorf("add nat postrouting jump rule: %v", err)
|
||||||
}
|
}
|
||||||
r.rules[jumpNat] = natRule
|
r.rules[jumpNatPost] = natRule
|
||||||
|
|
||||||
// Jump to prerouting chain
|
// Jump to mangle prerouting chain
|
||||||
preRule := []string{"-j", chainRTPRE}
|
preRule := []string{"-j", chainRTPRE}
|
||||||
if err := r.iptablesClient.Insert(tableMangle, chainPREROUTING, 1, preRule...); err != nil {
|
if err := r.iptablesClient.Insert(tableMangle, chainPREROUTING, 1, preRule...); err != nil {
|
||||||
return fmt.Errorf("add prerouting jump rule: %v", err)
|
return fmt.Errorf("add mangle prerouting jump rule: %v", err)
|
||||||
}
|
}
|
||||||
r.rules[jumpPre] = preRule
|
r.rules[jumpManglePre] = preRule
|
||||||
|
|
||||||
|
// Jump to nat prerouting chain
|
||||||
|
rdrRule := []string{"-j", chainRTRDR}
|
||||||
|
if err := r.iptablesClient.Insert(tableNat, chainPREROUTING, 1, rdrRule...); err != nil {
|
||||||
|
return fmt.Errorf("add nat prerouting jump rule: %v", err)
|
||||||
|
}
|
||||||
|
r.rules[jumpNatPre] = rdrRule
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *router) cleanJumpRules() error {
|
func (r *router) cleanJumpRules() error {
|
||||||
for _, ruleKey := range []string{jumpNat, jumpPre} {
|
for _, ruleKey := range []string{jumpNatPost, jumpManglePre, jumpNatPre} {
|
||||||
if rule, exists := r.rules[ruleKey]; exists {
|
if rule, exists := r.rules[ruleKey]; exists {
|
||||||
table := tableNat
|
var table, chain string
|
||||||
chain := chainPOSTROUTING
|
switch ruleKey {
|
||||||
if ruleKey == jumpPre {
|
case jumpNatPost:
|
||||||
|
table = tableNat
|
||||||
|
chain = chainPOSTROUTING
|
||||||
|
case jumpManglePre:
|
||||||
table = tableMangle
|
table = tableMangle
|
||||||
chain = chainPREROUTING
|
chain = chainPREROUTING
|
||||||
|
case jumpNatPre:
|
||||||
|
table = tableNat
|
||||||
|
chain = chainPREROUTING
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown jump rule: %s", ruleKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.iptablesClient.DeleteIfExists(table, chain, rule...); err != nil {
|
if err := r.iptablesClient.DeleteIfExists(table, chain, rule...); err != nil {
|
||||||
@@ -520,6 +547,8 @@ func (r *router) addNatRule(pair firewall.RouterPair) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.rules[ruleKey] = rule
|
r.rules[ruleKey] = rule
|
||||||
|
|
||||||
|
r.updateState()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,6 +564,7 @@ func (r *router) removeNatRule(pair firewall.RouterPair) error {
|
|||||||
log.Debugf("marking rule %s not found", ruleKey)
|
log.Debugf("marking rule %s not found", ruleKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r.updateState()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,6 +594,137 @@ func (r *router) updateState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *router) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
if err := r.ipFwdState.RequestForwarding(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKey := rule.ID()
|
||||||
|
if _, exists := r.rules[ruleKey+dnatSuffix]; exists {
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
toDestination := rule.TranslatedAddress.String()
|
||||||
|
switch {
|
||||||
|
case len(rule.TranslatedPort.Values) == 0:
|
||||||
|
// no translated port, use original port
|
||||||
|
case len(rule.TranslatedPort.Values) == 1:
|
||||||
|
toDestination += fmt.Sprintf(":%d", rule.TranslatedPort.Values[0])
|
||||||
|
case rule.TranslatedPort.IsRange && len(rule.TranslatedPort.Values) == 2:
|
||||||
|
// need the "/originalport" suffix to avoid dnat port randomization
|
||||||
|
toDestination += fmt.Sprintf(":%d-%d/%d", rule.TranslatedPort.Values[0], rule.TranslatedPort.Values[1], rule.DestinationPort.Values[0])
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid translated port: %v", rule.TranslatedPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
proto := strings.ToLower(string(rule.Protocol))
|
||||||
|
|
||||||
|
rules := make(map[string]ruleInfo, 3)
|
||||||
|
|
||||||
|
// DNAT rule
|
||||||
|
dnatRule := []string{
|
||||||
|
"!", "-i", r.wgIface.Name(),
|
||||||
|
"-p", proto,
|
||||||
|
"-j", "DNAT",
|
||||||
|
"--to-destination", toDestination,
|
||||||
|
}
|
||||||
|
dnatRule = append(dnatRule, applyPort("--dport", &rule.DestinationPort)...)
|
||||||
|
rules[ruleKey+dnatSuffix] = ruleInfo{
|
||||||
|
table: tableNat,
|
||||||
|
chain: chainRTRDR,
|
||||||
|
rule: dnatRule,
|
||||||
|
}
|
||||||
|
|
||||||
|
// SNAT rule
|
||||||
|
snatRule := []string{
|
||||||
|
"-o", r.wgIface.Name(),
|
||||||
|
"-p", proto,
|
||||||
|
"-d", rule.TranslatedAddress.String(),
|
||||||
|
"-j", "MASQUERADE",
|
||||||
|
}
|
||||||
|
snatRule = append(snatRule, applyPort("--dport", &rule.TranslatedPort)...)
|
||||||
|
rules[ruleKey+snatSuffix] = ruleInfo{
|
||||||
|
table: tableNat,
|
||||||
|
chain: chainRTNAT,
|
||||||
|
rule: snatRule,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forward filtering rule, if fwd policy is DROP
|
||||||
|
forwardRule := []string{
|
||||||
|
"-o", r.wgIface.Name(),
|
||||||
|
"-p", proto,
|
||||||
|
"-d", rule.TranslatedAddress.String(),
|
||||||
|
"-j", "ACCEPT",
|
||||||
|
}
|
||||||
|
forwardRule = append(forwardRule, applyPort("--dport", &rule.TranslatedPort)...)
|
||||||
|
rules[ruleKey+fwdSuffix] = ruleInfo{
|
||||||
|
table: tableFilter,
|
||||||
|
chain: chainRTFWDOUT,
|
||||||
|
rule: forwardRule,
|
||||||
|
}
|
||||||
|
|
||||||
|
for key, ruleInfo := range rules {
|
||||||
|
if err := r.iptablesClient.Append(ruleInfo.table, ruleInfo.chain, ruleInfo.rule...); err != nil {
|
||||||
|
if rollbackErr := r.rollbackRules(rules); rollbackErr != nil {
|
||||||
|
log.Errorf("rollback failed: %v", rollbackErr)
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("add rule %s: %w", key, err)
|
||||||
|
}
|
||||||
|
r.rules[key] = ruleInfo.rule
|
||||||
|
}
|
||||||
|
|
||||||
|
r.updateState()
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) rollbackRules(rules map[string]ruleInfo) error {
|
||||||
|
var merr *multierror.Error
|
||||||
|
for key, ruleInfo := range rules {
|
||||||
|
if err := r.iptablesClient.DeleteIfExists(ruleInfo.table, ruleInfo.chain, ruleInfo.rule...); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("rollback rule %s: %w", key, err))
|
||||||
|
// On rollback error, add to rules map for next cleanup
|
||||||
|
r.rules[key] = ruleInfo.rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if merr != nil {
|
||||||
|
r.updateState()
|
||||||
|
}
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
|
||||||
|
log.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKey := rule.ID()
|
||||||
|
|
||||||
|
var merr *multierror.Error
|
||||||
|
if dnatRule, exists := r.rules[ruleKey+dnatSuffix]; exists {
|
||||||
|
if err := r.iptablesClient.Delete(tableNat, chainRTRDR, dnatRule...); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete DNAT rule: %w", err))
|
||||||
|
}
|
||||||
|
delete(r.rules, ruleKey+dnatSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
if snatRule, exists := r.rules[ruleKey+snatSuffix]; exists {
|
||||||
|
if err := r.iptablesClient.Delete(tableNat, chainRTNAT, snatRule...); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete SNAT rule: %w", err))
|
||||||
|
}
|
||||||
|
delete(r.rules, ruleKey+snatSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fwdRule, exists := r.rules[ruleKey+fwdSuffix]; exists {
|
||||||
|
if err := r.iptablesClient.Delete(tableFilter, chainRTFWDIN, fwdRule...); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete forward rule: %w", err))
|
||||||
|
}
|
||||||
|
delete(r.rules, ruleKey+fwdSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.updateState()
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
|
}
|
||||||
|
|
||||||
func genRouteFilteringRuleSpec(params routeFilteringRuleParams) []string {
|
func genRouteFilteringRuleSpec(params routeFilteringRuleParams) []string {
|
||||||
var rule []string
|
var rule []string
|
||||||
|
|
||||||
|
|||||||
@@ -39,12 +39,14 @@ func TestIptablesManager_RestoreOrCreateContainers(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Now 5 rules:
|
// Now 5 rules:
|
||||||
// 1. established rule in forward chain
|
// 1. established rule forward in
|
||||||
// 2. jump rule to NAT chain
|
// 2. estbalished rule forward out
|
||||||
// 3. jump rule to PRE chain
|
// 3. jump rule to POST nat chain
|
||||||
// 4. static outbound masquerade rule
|
// 4. jump rule to PRE mangle chain
|
||||||
// 5. static return masquerade rule
|
// 5. jump rule to PRE nat chain
|
||||||
require.Len(t, manager.rules, 5, "should have created rules map")
|
// 6. static outbound masquerade rule
|
||||||
|
// 7. static return masquerade rule
|
||||||
|
require.Len(t, manager.rules, 7, "should have created rules map")
|
||||||
|
|
||||||
exists, err := manager.iptablesClient.Exists(tableNat, chainPOSTROUTING, "-j", chainRTNAT)
|
exists, err := manager.iptablesClient.Exists(tableNat, chainPOSTROUTING, "-j", chainRTNAT)
|
||||||
require.NoError(t, err, "should be able to query the iptables %s table and %s chain", tableNat, chainPOSTROUTING)
|
require.NoError(t, err, "should be able to query the iptables %s table and %s chain", tableNat, chainPOSTROUTING)
|
||||||
@@ -332,14 +334,14 @@ func TestRouter_AddRouteFiltering(t *testing.T) {
|
|||||||
require.NoError(t, err, "AddRouteFiltering failed")
|
require.NoError(t, err, "AddRouteFiltering failed")
|
||||||
|
|
||||||
// Check if the rule is in the internal map
|
// Check if the rule is in the internal map
|
||||||
rule, ok := r.rules[ruleKey.GetRuleID()]
|
rule, ok := r.rules[ruleKey.ID()]
|
||||||
assert.True(t, ok, "Rule not found in internal map")
|
assert.True(t, ok, "Rule not found in internal map")
|
||||||
|
|
||||||
// Log the internal rule
|
// Log the internal rule
|
||||||
t.Logf("Internal rule: %v", rule)
|
t.Logf("Internal rule: %v", rule)
|
||||||
|
|
||||||
// Check if the rule exists in iptables
|
// Check if the rule exists in iptables
|
||||||
exists, err := iptablesClient.Exists(tableFilter, chainRTFWD, rule...)
|
exists, err := iptablesClient.Exists(tableFilter, chainRTFWDIN, rule...)
|
||||||
assert.NoError(t, err, "Failed to check rule existence")
|
assert.NoError(t, err, "Failed to check rule existence")
|
||||||
assert.True(t, exists, "Rule not found in iptables")
|
assert.True(t, exists, "Rule not found in iptables")
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ type Rule struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRuleID returns the rule id
|
// GetRuleID returns the rule id
|
||||||
func (r *Rule) GetRuleID() string {
|
func (r *Rule) ID() string {
|
||||||
return r.ruleID
|
return r.ruleID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ const (
|
|||||||
// Each firewall type for different OS can use different type
|
// Each firewall type for different OS can use different type
|
||||||
// of the properties to hold data of the created rule
|
// of the properties to hold data of the created rule
|
||||||
type Rule interface {
|
type Rule interface {
|
||||||
// GetRuleID returns the rule id
|
// ID returns the rule id
|
||||||
GetRuleID() string
|
ID() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// RuleDirection is the traffic direction which a rule is applied
|
// RuleDirection is the traffic direction which a rule is applied
|
||||||
@@ -105,6 +105,12 @@ type Manager interface {
|
|||||||
EnableRouting() error
|
EnableRouting() error
|
||||||
|
|
||||||
DisableRouting() error
|
DisableRouting() error
|
||||||
|
|
||||||
|
// AddDNATRule adds a DNAT rule
|
||||||
|
AddDNATRule(ForwardRule) (Rule, error)
|
||||||
|
|
||||||
|
// DeleteDNATRule deletes a DNAT rule
|
||||||
|
DeleteDNATRule(Rule) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenKey(format string, pair RouterPair) string {
|
func GenKey(format string, pair RouterPair) string {
|
||||||
|
|||||||
27
client/firewall/manager/forward_rule.go
Normal file
27
client/firewall/manager/forward_rule.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ForwardRule todo figure out better place to this to avoid circular imports
|
||||||
|
type ForwardRule struct {
|
||||||
|
Protocol Protocol
|
||||||
|
DestinationPort Port
|
||||||
|
TranslatedAddress netip.Addr
|
||||||
|
TranslatedPort Port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ForwardRule) ID() string {
|
||||||
|
id := fmt.Sprintf("%s;%s;%s;%s",
|
||||||
|
r.Protocol,
|
||||||
|
r.DestinationPort.String(),
|
||||||
|
r.TranslatedAddress.String(),
|
||||||
|
r.TranslatedPort.String())
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r ForwardRule) String() string {
|
||||||
|
return fmt.Sprintf("protocol: %s, destinationPort: %s, translatedAddress: %s, translatedPort: %s", r.Protocol, r.DestinationPort.String(), r.TranslatedAddress.String(), r.TranslatedPort.String())
|
||||||
|
}
|
||||||
@@ -1,30 +1,12 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Protocol is the protocol of the port
|
|
||||||
type Protocol string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// ProtocolTCP is the TCP protocol
|
|
||||||
ProtocolTCP Protocol = "tcp"
|
|
||||||
|
|
||||||
// ProtocolUDP is the UDP protocol
|
|
||||||
ProtocolUDP Protocol = "udp"
|
|
||||||
|
|
||||||
// ProtocolICMP is the ICMP protocol
|
|
||||||
ProtocolICMP Protocol = "icmp"
|
|
||||||
|
|
||||||
// ProtocolALL cover all supported protocols
|
|
||||||
ProtocolALL Protocol = "all"
|
|
||||||
|
|
||||||
// ProtocolUnknown unknown protocol
|
|
||||||
ProtocolUnknown Protocol = "unknown"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Port of the address for firewall rule
|
// Port of the address for firewall rule
|
||||||
|
// todo Move Protocol and Port and RouterPair to the Firwall package or a separate package
|
||||||
type Port struct {
|
type Port struct {
|
||||||
// IsRange is true Values contains two values, the first is the start port, the second is the end port
|
// IsRange is true Values contains two values, the first is the start port, the second is the end port
|
||||||
IsRange bool
|
IsRange bool
|
||||||
@@ -33,6 +15,25 @@ type Port struct {
|
|||||||
Values []uint16
|
Values []uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPort(ports ...int) (*Port, error) {
|
||||||
|
if len(ports) == 0 {
|
||||||
|
return nil, fmt.Errorf("no port provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
ports16 := make([]uint16, len(ports))
|
||||||
|
for i, port := range ports {
|
||||||
|
if port < 1 || port > 65535 {
|
||||||
|
return nil, fmt.Errorf("invalid port number: %d (must be between 1-65535)", port)
|
||||||
|
}
|
||||||
|
ports16[i] = uint16(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Port{
|
||||||
|
IsRange: len(ports) > 1,
|
||||||
|
Values: ports16,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// String interface implementation
|
// String interface implementation
|
||||||
func (p *Port) String() string {
|
func (p *Port) String() string {
|
||||||
var ports string
|
var ports string
|
||||||
|
|||||||
19
client/firewall/manager/protocol.go
Normal file
19
client/firewall/manager/protocol.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
// Protocol is the protocol of the port
|
||||||
|
// todo Move Protocol and Port and RouterPair to the Firwall package or a separate package
|
||||||
|
type Protocol string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ProtocolTCP is the TCP protocol
|
||||||
|
ProtocolTCP Protocol = "tcp"
|
||||||
|
|
||||||
|
// ProtocolUDP is the UDP protocol
|
||||||
|
ProtocolUDP Protocol = "udp"
|
||||||
|
|
||||||
|
// ProtocolICMP is the ICMP protocol
|
||||||
|
ProtocolICMP Protocol = "icmp"
|
||||||
|
|
||||||
|
// ProtocolALL cover all supported protocols
|
||||||
|
ProtocolALL Protocol = "all"
|
||||||
|
)
|
||||||
@@ -127,7 +127,7 @@ func (m *AclManager) DeletePeerRule(rule firewall.Rule) error {
|
|||||||
log.Errorf("failed to delete mangle rule: %v", err)
|
log.Errorf("failed to delete mangle rule: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m.rules, r.GetRuleID())
|
delete(m.rules, r.ID())
|
||||||
return m.rConn.Flush()
|
return m.rConn.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ func (m *AclManager) DeletePeerRule(rule firewall.Rule) error {
|
|||||||
log.Errorf("failed to delete mangle rule: %v", err)
|
log.Errorf("failed to delete mangle rule: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(m.rules, r.GetRuleID())
|
delete(m.rules, r.ID())
|
||||||
return m.rConn.Flush()
|
return m.rConn.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ func (m *AclManager) DeletePeerRule(rule firewall.Rule) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(m.rules, r.GetRuleID())
|
delete(m.rules, r.ID())
|
||||||
m.ipsetStore.DeleteReferenceFromIpSet(r.nftSet.Name)
|
m.ipsetStore.DeleteReferenceFromIpSet(r.nftSet.Name)
|
||||||
|
|
||||||
if m.ipsetStore.HasReferenceToSet(r.nftSet.Name) {
|
if m.ipsetStore.HasReferenceToSet(r.nftSet.Name) {
|
||||||
|
|||||||
@@ -342,6 +342,22 @@ func (m *Manager) Flush() error {
|
|||||||
return m.aclManager.Flush()
|
return m.aclManager.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddDNATRule adds a DNAT rule
|
||||||
|
func (m *Manager) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.router.AddDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDNATRule deletes a DNAT rule
|
||||||
|
func (m *Manager) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
return m.router.DeleteDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) createWorkTable() (*nftables.Table, error) {
|
func (m *Manager) createWorkTable() (*nftables.Table, error) {
|
||||||
tables, err := m.rConn.ListTablesOfFamily(nftables.TableFamilyIPv4)
|
tables, err := m.rConn.ListTablesOfFamily(nftables.TableFamilyIPv4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -14,23 +14,31 @@ import (
|
|||||||
"github.com/google/nftables"
|
"github.com/google/nftables"
|
||||||
"github.com/google/nftables/binaryutil"
|
"github.com/google/nftables/binaryutil"
|
||||||
"github.com/google/nftables/expr"
|
"github.com/google/nftables/expr"
|
||||||
|
"github.com/google/nftables/xt"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/internal/acl/id"
|
"github.com/netbirdio/netbird/client/internal/acl/id"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/routemanager/ipfwdstate"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
"github.com/netbirdio/netbird/client/internal/routemanager/refcounter"
|
||||||
nbnet "github.com/netbirdio/netbird/util/net"
|
nbnet "github.com/netbirdio/netbird/util/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
chainNameRoutingFw = "netbird-rt-fwd"
|
tableNat = "nat"
|
||||||
chainNameRoutingNat = "netbird-rt-postrouting"
|
chainNameNatPrerouting = "PREROUTING"
|
||||||
chainNameForward = "FORWARD"
|
chainNameRoutingFw = "netbird-rt-fwd"
|
||||||
|
chainNameRoutingNat = "netbird-rt-postrouting"
|
||||||
|
chainNameRoutingRdr = "netbird-rt-redirect"
|
||||||
|
chainNameForward = "FORWARD"
|
||||||
|
|
||||||
userDataAcceptForwardRuleIif = "frwacceptiif"
|
userDataAcceptForwardRuleIif = "frwacceptiif"
|
||||||
userDataAcceptForwardRuleOif = "frwacceptoif"
|
userDataAcceptForwardRuleOif = "frwacceptoif"
|
||||||
|
|
||||||
|
dnatSuffix = "_dnat"
|
||||||
|
snatSuffix = "_snat"
|
||||||
)
|
)
|
||||||
|
|
||||||
const refreshRulesMapError = "refresh rules map: %w"
|
const refreshRulesMapError = "refresh rules map: %w"
|
||||||
@@ -49,16 +57,18 @@ type router struct {
|
|||||||
ipsetCounter *refcounter.Counter[string, []netip.Prefix, *nftables.Set]
|
ipsetCounter *refcounter.Counter[string, []netip.Prefix, *nftables.Set]
|
||||||
|
|
||||||
wgIface iFaceMapper
|
wgIface iFaceMapper
|
||||||
|
ipFwdState *ipfwdstate.IPForwardingState
|
||||||
legacyManagement bool
|
legacyManagement bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRouter(workTable *nftables.Table, wgIface iFaceMapper) (*router, error) {
|
func newRouter(workTable *nftables.Table, wgIface iFaceMapper) (*router, error) {
|
||||||
r := &router{
|
r := &router{
|
||||||
conn: &nftables.Conn{},
|
conn: &nftables.Conn{},
|
||||||
workTable: workTable,
|
workTable: workTable,
|
||||||
chains: make(map[string]*nftables.Chain),
|
chains: make(map[string]*nftables.Chain),
|
||||||
rules: make(map[string]*nftables.Rule),
|
rules: make(map[string]*nftables.Rule),
|
||||||
wgIface: wgIface,
|
wgIface: wgIface,
|
||||||
|
ipFwdState: ipfwdstate.NewIPForwardingState(),
|
||||||
}
|
}
|
||||||
|
|
||||||
r.ipsetCounter = refcounter.New(
|
r.ipsetCounter = refcounter.New(
|
||||||
@@ -98,7 +108,52 @@ func (r *router) Reset() error {
|
|||||||
// clear without deleting the ipsets, the nf table will be deleted by the caller
|
// clear without deleting the ipsets, the nf table will be deleted by the caller
|
||||||
r.ipsetCounter.Clear()
|
r.ipsetCounter.Clear()
|
||||||
|
|
||||||
return r.removeAcceptForwardRules()
|
var merr *multierror.Error
|
||||||
|
|
||||||
|
if err := r.removeAcceptForwardRules(); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("remove accept forward rules: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.removeNatPreroutingRules(); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("remove filter prerouting rules: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) removeNatPreroutingRules() error {
|
||||||
|
table := &nftables.Table{
|
||||||
|
Name: tableNat,
|
||||||
|
Family: nftables.TableFamilyIPv4,
|
||||||
|
}
|
||||||
|
chain := &nftables.Chain{
|
||||||
|
Name: chainNameNatPrerouting,
|
||||||
|
Table: table,
|
||||||
|
Hooknum: nftables.ChainHookPrerouting,
|
||||||
|
Priority: nftables.ChainPriorityNATDest,
|
||||||
|
Type: nftables.ChainTypeNAT,
|
||||||
|
}
|
||||||
|
rules, err := r.conn.GetRules(table, chain)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("get rules from nat table: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var merr *multierror.Error
|
||||||
|
|
||||||
|
// Delete rules that have our UserData suffix
|
||||||
|
for _, rule := range rules {
|
||||||
|
if len(rule.UserData) == 0 || !strings.HasSuffix(string(rule.UserData), dnatSuffix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := r.conn.DelRule(rule); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete rule %s: %w", rule.UserData, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.conn.Flush(); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf(flushError, err))
|
||||||
|
}
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *router) loadFilterTable() (*nftables.Table, error) {
|
func (r *router) loadFilterTable() (*nftables.Table, error) {
|
||||||
@@ -133,14 +188,22 @@ func (r *router) createContainers() error {
|
|||||||
Type: nftables.ChainTypeNAT,
|
Type: nftables.ChainTypeNAT,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
r.chains[chainNameRoutingRdr] = r.conn.AddChain(&nftables.Chain{
|
||||||
|
Name: chainNameRoutingRdr,
|
||||||
|
Table: r.workTable,
|
||||||
|
Hooknum: nftables.ChainHookPrerouting,
|
||||||
|
Priority: nftables.ChainPriorityNATDest,
|
||||||
|
Type: nftables.ChainTypeNAT,
|
||||||
|
})
|
||||||
|
|
||||||
// Chain is created by acl manager
|
// Chain is created by acl manager
|
||||||
// TODO: move creation to a common place
|
// TODO: move creation to a common place
|
||||||
r.chains[chainNamePrerouting] = &nftables.Chain{
|
r.chains[chainNamePrerouting] = &nftables.Chain{
|
||||||
Name: chainNamePrerouting,
|
Name: chainNamePrerouting,
|
||||||
Table: r.workTable,
|
Table: r.workTable,
|
||||||
Type: nftables.ChainTypeFilter,
|
|
||||||
Hooknum: nftables.ChainHookPrerouting,
|
Hooknum: nftables.ChainHookPrerouting,
|
||||||
Priority: nftables.ChainPriorityMangle,
|
Priority: nftables.ChainPriorityMangle,
|
||||||
|
Type: nftables.ChainTypeFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the single NAT rule that matches on mark
|
// Add the single NAT rule that matches on mark
|
||||||
@@ -281,7 +344,7 @@ func (r *router) DeleteRouteRule(rule firewall.Rule) error {
|
|||||||
return fmt.Errorf(refreshRulesMapError, err)
|
return fmt.Errorf(refreshRulesMapError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleKey := rule.GetRuleID()
|
ruleKey := rule.ID()
|
||||||
nftRule, exists := r.rules[ruleKey]
|
nftRule, exists := r.rules[ruleKey]
|
||||||
if !exists {
|
if !exists {
|
||||||
log.Debugf("route rule %s not found", ruleKey)
|
log.Debugf("route rule %s not found", ruleKey)
|
||||||
@@ -410,6 +473,10 @@ func (r *router) deleteNftRule(rule *nftables.Rule, ruleKey string) error {
|
|||||||
|
|
||||||
// AddNatRule appends a nftables rule pair to the nat chain
|
// AddNatRule appends a nftables rule pair to the nat chain
|
||||||
func (r *router) AddNatRule(pair firewall.RouterPair) error {
|
func (r *router) AddNatRule(pair firewall.RouterPair) error {
|
||||||
|
if err := r.ipFwdState.RequestForwarding(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := r.refreshRulesMap(); err != nil {
|
if err := r.refreshRulesMap(); err != nil {
|
||||||
return fmt.Errorf(refreshRulesMapError, err)
|
return fmt.Errorf(refreshRulesMapError, err)
|
||||||
}
|
}
|
||||||
@@ -836,6 +903,10 @@ func (r *router) removeAcceptForwardRulesIptables(ipt *iptables.IPTables) error
|
|||||||
|
|
||||||
// RemoveNatRule removes the prerouting mark rule
|
// RemoveNatRule removes the prerouting mark rule
|
||||||
func (r *router) RemoveNatRule(pair firewall.RouterPair) error {
|
func (r *router) RemoveNatRule(pair firewall.RouterPair) error {
|
||||||
|
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
|
||||||
|
log.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := r.refreshRulesMap(); err != nil {
|
if err := r.refreshRulesMap(); err != nil {
|
||||||
return fmt.Errorf(refreshRulesMapError, err)
|
return fmt.Errorf(refreshRulesMapError, err)
|
||||||
}
|
}
|
||||||
@@ -896,6 +967,269 @@ func (r *router) refreshRulesMap() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *router) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
if err := r.ipFwdState.RequestForwarding(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKey := rule.ID()
|
||||||
|
if _, exists := r.rules[ruleKey+dnatSuffix]; exists {
|
||||||
|
return rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
protoNum, err := protoToInt(rule.Protocol)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("convert protocol to number: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.addDnatRedirect(rule, protoNum, ruleKey); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
r.addDnatMasq(rule, protoNum, ruleKey)
|
||||||
|
|
||||||
|
// Unlike iptables, there's no point in adding "out" rules in the forward chain here as our policy is ACCEPT.
|
||||||
|
// To overcome DROP policies in other chains, we'd have to add rules to the chains there.
|
||||||
|
// We also cannot just add "oif <iface> accept" there and filter in our own table as we don't know what is supposed to be allowed.
|
||||||
|
// TODO: find chains with drop policies and add rules there
|
||||||
|
|
||||||
|
if err := r.conn.Flush(); err != nil {
|
||||||
|
return nil, fmt.Errorf("flush rules: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) addDnatRedirect(rule firewall.ForwardRule, protoNum uint8, ruleKey string) error {
|
||||||
|
dnatExprs := []expr.Any{
|
||||||
|
&expr.Meta{Key: expr.MetaKeyIIFNAME, Register: 1},
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpNeq,
|
||||||
|
Register: 1,
|
||||||
|
Data: ifname(r.wgIface.Name()),
|
||||||
|
},
|
||||||
|
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{protoNum},
|
||||||
|
},
|
||||||
|
&expr.Payload{
|
||||||
|
DestRegister: 1,
|
||||||
|
Base: expr.PayloadBaseTransportHeader,
|
||||||
|
Offset: 2,
|
||||||
|
Len: 2,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
dnatExprs = append(dnatExprs, applyPort(&rule.DestinationPort, false)...)
|
||||||
|
|
||||||
|
// shifted translated port is not supported in nftables, so we hand this over to xtables
|
||||||
|
if rule.TranslatedPort.IsRange && len(rule.TranslatedPort.Values) == 2 {
|
||||||
|
if rule.TranslatedPort.Values[0] != rule.DestinationPort.Values[0] ||
|
||||||
|
rule.TranslatedPort.Values[1] != rule.DestinationPort.Values[1] {
|
||||||
|
return r.addXTablesRedirect(dnatExprs, ruleKey, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
additionalExprs, regProtoMin, regProtoMax, err := r.handleTranslatedPort(rule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dnatExprs = append(dnatExprs, additionalExprs...)
|
||||||
|
|
||||||
|
dnatExprs = append(dnatExprs,
|
||||||
|
&expr.NAT{
|
||||||
|
Type: expr.NATTypeDestNAT,
|
||||||
|
Family: uint32(nftables.TableFamilyIPv4),
|
||||||
|
RegAddrMin: 1,
|
||||||
|
RegProtoMin: regProtoMin,
|
||||||
|
RegProtoMax: regProtoMax,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
dnatRule := &nftables.Rule{
|
||||||
|
Table: r.workTable,
|
||||||
|
Chain: r.chains[chainNameRoutingRdr],
|
||||||
|
Exprs: dnatExprs,
|
||||||
|
UserData: []byte(ruleKey + dnatSuffix),
|
||||||
|
}
|
||||||
|
r.conn.AddRule(dnatRule)
|
||||||
|
r.rules[ruleKey+dnatSuffix] = dnatRule
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) handleTranslatedPort(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {
|
||||||
|
switch {
|
||||||
|
case rule.TranslatedPort.IsRange && len(rule.TranslatedPort.Values) == 2:
|
||||||
|
return r.handlePortRange(rule)
|
||||||
|
case len(rule.TranslatedPort.Values) == 0:
|
||||||
|
return r.handleAddressOnly(rule)
|
||||||
|
case len(rule.TranslatedPort.Values) == 1:
|
||||||
|
return r.handleSinglePort(rule)
|
||||||
|
default:
|
||||||
|
return nil, 0, 0, fmt.Errorf("invalid translated port: %v", rule.TranslatedPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) handlePortRange(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {
|
||||||
|
exprs := []expr.Any{
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 1,
|
||||||
|
Data: rule.TranslatedAddress.AsSlice(),
|
||||||
|
},
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 2,
|
||||||
|
Data: binaryutil.BigEndian.PutUint16(rule.TranslatedPort.Values[0]),
|
||||||
|
},
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 3,
|
||||||
|
Data: binaryutil.BigEndian.PutUint16(rule.TranslatedPort.Values[1]),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exprs, 2, 3, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) handleAddressOnly(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {
|
||||||
|
exprs := []expr.Any{
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 1,
|
||||||
|
Data: rule.TranslatedAddress.AsSlice(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exprs, 0, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) handleSinglePort(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {
|
||||||
|
exprs := []expr.Any{
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 1,
|
||||||
|
Data: rule.TranslatedAddress.AsSlice(),
|
||||||
|
},
|
||||||
|
&expr.Immediate{
|
||||||
|
Register: 2,
|
||||||
|
Data: binaryutil.BigEndian.PutUint16(rule.TranslatedPort.Values[0]),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return exprs, 2, 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) addXTablesRedirect(dnatExprs []expr.Any, ruleKey string, rule firewall.ForwardRule) error {
|
||||||
|
dnatExprs = append(dnatExprs,
|
||||||
|
&expr.Counter{},
|
||||||
|
&expr.Target{
|
||||||
|
Name: "DNAT",
|
||||||
|
Rev: 2,
|
||||||
|
Info: &xt.NatRange2{
|
||||||
|
NatRange: xt.NatRange{
|
||||||
|
Flags: uint(xt.NatRangeMapIPs | xt.NatRangeProtoSpecified | xt.NatRangeProtoOffset),
|
||||||
|
MinIP: rule.TranslatedAddress.AsSlice(),
|
||||||
|
MaxIP: rule.TranslatedAddress.AsSlice(),
|
||||||
|
MinPort: rule.TranslatedPort.Values[0],
|
||||||
|
MaxPort: rule.TranslatedPort.Values[1],
|
||||||
|
},
|
||||||
|
BasePort: rule.DestinationPort.Values[0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
dnatRule := &nftables.Rule{
|
||||||
|
Table: &nftables.Table{
|
||||||
|
Name: tableNat,
|
||||||
|
Family: nftables.TableFamilyIPv4,
|
||||||
|
},
|
||||||
|
Chain: &nftables.Chain{
|
||||||
|
Name: chainNameNatPrerouting,
|
||||||
|
Table: r.filterTable,
|
||||||
|
Type: nftables.ChainTypeNAT,
|
||||||
|
Hooknum: nftables.ChainHookPrerouting,
|
||||||
|
Priority: nftables.ChainPriorityNATDest,
|
||||||
|
},
|
||||||
|
Exprs: dnatExprs,
|
||||||
|
UserData: []byte(ruleKey + dnatSuffix),
|
||||||
|
}
|
||||||
|
r.conn.AddRule(dnatRule)
|
||||||
|
r.rules[ruleKey+dnatSuffix] = dnatRule
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) addDnatMasq(rule firewall.ForwardRule, protoNum uint8, ruleKey string) {
|
||||||
|
masqExprs := []expr.Any{
|
||||||
|
&expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: ifname(r.wgIface.Name()),
|
||||||
|
},
|
||||||
|
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: []byte{protoNum},
|
||||||
|
},
|
||||||
|
&expr.Payload{
|
||||||
|
DestRegister: 1,
|
||||||
|
Base: expr.PayloadBaseNetworkHeader,
|
||||||
|
Offset: 16,
|
||||||
|
Len: 4,
|
||||||
|
},
|
||||||
|
&expr.Cmp{
|
||||||
|
Op: expr.CmpOpEq,
|
||||||
|
Register: 1,
|
||||||
|
Data: rule.TranslatedAddress.AsSlice(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
masqExprs = append(masqExprs, applyPort(&rule.TranslatedPort, false)...)
|
||||||
|
masqExprs = append(masqExprs, &expr.Masq{})
|
||||||
|
|
||||||
|
masqRule := &nftables.Rule{
|
||||||
|
Table: r.workTable,
|
||||||
|
Chain: r.chains[chainNameRoutingNat],
|
||||||
|
Exprs: masqExprs,
|
||||||
|
UserData: []byte(ruleKey + snatSuffix),
|
||||||
|
}
|
||||||
|
r.conn.AddRule(masqRule)
|
||||||
|
r.rules[ruleKey+snatSuffix] = masqRule
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *router) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
if err := r.ipFwdState.ReleaseForwarding(); err != nil {
|
||||||
|
log.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleKey := rule.ID()
|
||||||
|
|
||||||
|
if err := r.refreshRulesMap(); err != nil {
|
||||||
|
return fmt.Errorf(refreshRulesMapError, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var merr *multierror.Error
|
||||||
|
if dnatRule, exists := r.rules[ruleKey+dnatSuffix]; exists {
|
||||||
|
if err := r.conn.DelRule(dnatRule); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete dnat rule: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if masqRule, exists := r.rules[ruleKey+snatSuffix]; exists {
|
||||||
|
if err := r.conn.DelRule(masqRule); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("delete snat rule: %w", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.conn.Flush(); err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf(flushError, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if merr == nil {
|
||||||
|
delete(r.rules, ruleKey+dnatSuffix)
|
||||||
|
delete(r.rules, ruleKey+snatSuffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
|
}
|
||||||
|
|
||||||
// generateCIDRMatcherExpressions generates nftables expressions that matches a CIDR
|
// generateCIDRMatcherExpressions generates nftables expressions that matches a CIDR
|
||||||
func generateCIDRMatcherExpressions(source bool, prefix netip.Prefix) []expr.Any {
|
func generateCIDRMatcherExpressions(source bool, prefix netip.Prefix) []expr.Any {
|
||||||
var offset uint32
|
var offset uint32
|
||||||
@@ -959,15 +1293,11 @@ func applyPort(port *firewall.Port, isSource bool) []expr.Any {
|
|||||||
if port.IsRange && len(port.Values) == 2 {
|
if port.IsRange && len(port.Values) == 2 {
|
||||||
// Handle port range
|
// Handle port range
|
||||||
exprs = append(exprs,
|
exprs = append(exprs,
|
||||||
&expr.Cmp{
|
&expr.Range{
|
||||||
Op: expr.CmpOpGte,
|
Op: expr.CmpOpEq,
|
||||||
Register: 1,
|
Register: 1,
|
||||||
Data: binaryutil.BigEndian.PutUint16(port.Values[0]),
|
FromData: binaryutil.BigEndian.PutUint16(port.Values[0]),
|
||||||
},
|
ToData: binaryutil.BigEndian.PutUint16(port.Values[1]),
|
||||||
&expr.Cmp{
|
|
||||||
Op: expr.CmpOpLte,
|
|
||||||
Register: 1,
|
|
||||||
Data: binaryutil.BigEndian.PutUint16(port.Values[1]),
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -319,7 +319,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Check if the rule is in the internal map
|
// Check if the rule is in the internal map
|
||||||
rule, ok := r.rules[ruleKey.GetRuleID()]
|
rule, ok := r.rules[ruleKey.ID()]
|
||||||
assert.True(t, ok, "Rule not found in internal map")
|
assert.True(t, ok, "Rule not found in internal map")
|
||||||
|
|
||||||
t.Log("Internal rule expressions:")
|
t.Log("Internal rule expressions:")
|
||||||
@@ -336,7 +336,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) {
|
|||||||
|
|
||||||
var nftRule *nftables.Rule
|
var nftRule *nftables.Rule
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if string(rule.UserData) == ruleKey.GetRuleID() {
|
if string(rule.UserData) == ruleKey.ID() {
|
||||||
nftRule = rule
|
nftRule = rule
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -595,16 +595,20 @@ func containsPort(exprs []expr.Any, port *firewall.Port, isSource bool) bool {
|
|||||||
if ex.Base == expr.PayloadBaseTransportHeader && ex.Offset == offset && ex.Len == 2 {
|
if ex.Base == expr.PayloadBaseTransportHeader && ex.Offset == offset && ex.Len == 2 {
|
||||||
payloadFound = true
|
payloadFound = true
|
||||||
}
|
}
|
||||||
case *expr.Cmp:
|
case *expr.Range:
|
||||||
if port.IsRange {
|
if port.IsRange && len(port.Values) == 2 {
|
||||||
if ex.Op == expr.CmpOpGte || ex.Op == expr.CmpOpLte {
|
fromPort := binary.BigEndian.Uint16(ex.FromData)
|
||||||
|
toPort := binary.BigEndian.Uint16(ex.ToData)
|
||||||
|
if fromPort == port.Values[0] && toPort == port.Values[1] {
|
||||||
portMatchFound = true
|
portMatchFound = true
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
case *expr.Cmp:
|
||||||
|
if !port.IsRange {
|
||||||
if ex.Op == expr.CmpOpEq && len(ex.Data) == 2 {
|
if ex.Op == expr.CmpOpEq && len(ex.Data) == 2 {
|
||||||
portValue := binary.BigEndian.Uint16(ex.Data)
|
portValue := binary.BigEndian.Uint16(ex.Data)
|
||||||
for _, p := range port.Values {
|
for _, p := range port.Values {
|
||||||
if uint16(p) == portValue {
|
if p == portValue {
|
||||||
portMatchFound = true
|
portMatchFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ type Rule struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetRuleID returns the rule id
|
// GetRuleID returns the rule id
|
||||||
func (r *Rule) GetRuleID() string {
|
func (r *Rule) ID() string {
|
||||||
return r.ruleID
|
return r.ruleID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ type PeerRule struct {
|
|||||||
udpHook func([]byte) bool
|
udpHook func([]byte) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRuleID returns the rule id
|
// ID returns the rule id
|
||||||
func (r *PeerRule) GetRuleID() string {
|
func (r *PeerRule) ID() string {
|
||||||
return r.id
|
return r.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ type RouteRule struct {
|
|||||||
action firewall.Action
|
action firewall.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRuleID returns the rule id
|
// ID returns the rule id
|
||||||
func (r *RouteRule) GetRuleID() string {
|
func (r *RouteRule) ID() string {
|
||||||
return r.id
|
return r.id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ const (
|
|||||||
EnvEnableNetstackLocalForwarding = "NB_ENABLE_NETSTACK_LOCAL_FORWARDING"
|
EnvEnableNetstackLocalForwarding = "NB_ENABLE_NETSTACK_LOCAL_FORWARDING"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errNatNotSupported = errors.New("nat not supported with userspace firewall")
|
||||||
|
|
||||||
// RuleSet is a set of rules grouped by a string key
|
// RuleSet is a set of rules grouped by a string key
|
||||||
type RuleSet map[string]PeerRule
|
type RuleSet map[string]PeerRule
|
||||||
|
|
||||||
@@ -437,7 +439,7 @@ func (m *Manager) DeleteRouteRule(rule firewall.Rule) error {
|
|||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
ruleID := rule.GetRuleID()
|
ruleID := rule.ID()
|
||||||
idx := slices.IndexFunc(m.routeRules, func(r RouteRule) bool {
|
idx := slices.IndexFunc(m.routeRules, func(r RouteRule) bool {
|
||||||
return r.id == ruleID
|
return r.id == ruleID
|
||||||
})
|
})
|
||||||
@@ -478,6 +480,22 @@ func (m *Manager) SetLegacyManagement(isLegacy bool) error {
|
|||||||
// Flush doesn't need to be implemented for this manager
|
// Flush doesn't need to be implemented for this manager
|
||||||
func (m *Manager) Flush() error { return nil }
|
func (m *Manager) Flush() error { return nil }
|
||||||
|
|
||||||
|
// AddDNATRule adds a DNAT rule
|
||||||
|
func (m *Manager) AddDNATRule(rule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
if m.nativeFirewall == nil {
|
||||||
|
return nil, errNatNotSupported
|
||||||
|
}
|
||||||
|
return m.nativeFirewall.AddDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteDNATRule deletes a DNAT rule
|
||||||
|
func (m *Manager) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
if m.nativeFirewall == nil {
|
||||||
|
return errNatNotSupported
|
||||||
|
}
|
||||||
|
return m.nativeFirewall.DeleteDNATRule(rule)
|
||||||
|
}
|
||||||
|
|
||||||
// DropOutgoing filter outgoing packets
|
// DropOutgoing filter outgoing packets
|
||||||
func (m *Manager) DropOutgoing(packetData []byte) bool {
|
func (m *Manager) DropOutgoing(packetData []byte) bool {
|
||||||
return m.processOutgoingHooks(packetData)
|
return m.processOutgoingHooks(packetData)
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func TestManagerDeleteRule(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range rule2 {
|
for _, r := range rule2 {
|
||||||
if _, ok := m.incomingRules[ip.String()][r.GetRuleID()]; !ok {
|
if _, ok := m.incomingRules[ip.String()][r.ID()]; !ok {
|
||||||
t.Errorf("rule2 is not in the incomingRules")
|
t.Errorf("rule2 is not in the incomingRules")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ func TestManagerDeleteRule(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range rule2 {
|
for _, r := range rule2 {
|
||||||
if _, ok := m.incomingRules[ip.String()][r.GetRuleID()]; ok {
|
if _, ok := m.incomingRules[ip.String()][r.ID()]; ok {
|
||||||
t.Errorf("rule2 is not in the incomingRules")
|
t.Errorf("rule2 is not in the incomingRules")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
type RuleID string
|
type RuleID string
|
||||||
|
|
||||||
func (r RuleID) GetRuleID() string {
|
func (r RuleID) ID() string {
|
||||||
return string(r)
|
return string(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ func (d *DefaultManager) applyRouteACL(rule *mgmProto.RouteFirewallRule) (id.Rul
|
|||||||
return "", fmt.Errorf("add route rule: %w", err)
|
return "", fmt.Errorf("add route rule: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return id.RuleID(addedRule.GetRuleID()), nil
|
return id.RuleID(addedRule.ID()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DefaultManager) protoRuleToFirewallRule(
|
func (d *DefaultManager) protoRuleToFirewallRule(
|
||||||
@@ -515,7 +515,7 @@ func (d *DefaultManager) rollBack(newRulePairs map[id.RuleID][]firewall.Rule) {
|
|||||||
for _, rules := range newRulePairs {
|
for _, rules := range newRulePairs {
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if err := d.firewall.DeletePeerRule(rule); err != nil {
|
if err := d.firewall.DeletePeerRule(rule); err != nil {
|
||||||
log.Errorf("failed to delete new firewall rule (id: %v) during rollback: %v", rule.GetRuleID(), err)
|
log.Errorf("failed to delete new firewall rule (id: %v) during rollback: %v", rule.ID(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func TestDefaultManager(t *testing.T) {
|
|||||||
t.Run("add extra rules", func(t *testing.T) {
|
t.Run("add extra rules", func(t *testing.T) {
|
||||||
existedPairs := map[string]struct{}{}
|
existedPairs := map[string]struct{}{}
|
||||||
for id := range acl.peerRulesPairs {
|
for id := range acl.peerRulesPairs {
|
||||||
existedPairs[id.GetRuleID()] = struct{}{}
|
existedPairs[id.ID()] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove first rule
|
// remove first rule
|
||||||
@@ -100,7 +100,7 @@ func TestDefaultManager(t *testing.T) {
|
|||||||
// check that old rule was removed
|
// check that old rule was removed
|
||||||
previousCount := 0
|
previousCount := 0
|
||||||
for id := range acl.peerRulesPairs {
|
for id := range acl.peerRulesPairs {
|
||||||
if _, ok := existedPairs[id.GetRuleID()]; ok {
|
if _, ok := existedPairs[id.ID()]; ok {
|
||||||
previousCount++
|
previousCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
nberrors "github.com/netbirdio/netbird/client/errors"
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
"github.com/netbirdio/netbird/client/firewall"
|
"github.com/netbirdio/netbird/client/firewall"
|
||||||
"github.com/netbirdio/netbird/client/firewall/manager"
|
firewallManager "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface"
|
"github.com/netbirdio/netbird/client/iface"
|
||||||
"github.com/netbirdio/netbird/client/iface/bind"
|
"github.com/netbirdio/netbird/client/iface/bind"
|
||||||
"github.com/netbirdio/netbird/client/iface/device"
|
"github.com/netbirdio/netbird/client/iface/device"
|
||||||
@@ -33,6 +33,9 @@ import (
|
|||||||
"github.com/netbirdio/netbird/client/internal/acl"
|
"github.com/netbirdio/netbird/client/internal/acl"
|
||||||
"github.com/netbirdio/netbird/client/internal/dns"
|
"github.com/netbirdio/netbird/client/internal/dns"
|
||||||
"github.com/netbirdio/netbird/client/internal/dnsfwd"
|
"github.com/netbirdio/netbird/client/internal/dnsfwd"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/ingressgw"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
"github.com/netbirdio/netbird/client/internal/networkmonitor"
|
"github.com/netbirdio/netbird/client/internal/networkmonitor"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer/guard"
|
"github.com/netbirdio/netbird/client/internal/peer/guard"
|
||||||
@@ -169,10 +172,11 @@ type Engine struct {
|
|||||||
|
|
||||||
statusRecorder *peer.Status
|
statusRecorder *peer.Status
|
||||||
|
|
||||||
firewall manager.Manager
|
firewall firewallManager.Manager
|
||||||
routeManager routemanager.Manager
|
routeManager routemanager.Manager
|
||||||
acl acl.Manager
|
acl acl.Manager
|
||||||
dnsForwardMgr *dnsfwd.Manager
|
dnsForwardMgr *dnsfwd.Manager
|
||||||
|
ingressGatewayMgr *ingressgw.Manager
|
||||||
|
|
||||||
dnsServer dns.Server
|
dnsServer dns.Server
|
||||||
|
|
||||||
@@ -187,6 +191,7 @@ type Engine struct {
|
|||||||
persistNetworkMap bool
|
persistNetworkMap bool
|
||||||
latestNetworkMap *mgmProto.NetworkMap
|
latestNetworkMap *mgmProto.NetworkMap
|
||||||
connSemaphore *semaphoregroup.SemaphoreGroup
|
connSemaphore *semaphoregroup.SemaphoreGroup
|
||||||
|
flowManager types.FlowManager
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer is an instance of the Connection Peer
|
// Peer is an instance of the Connection Peer
|
||||||
@@ -229,6 +234,7 @@ func NewEngine(
|
|||||||
statusRecorder: statusRecorder,
|
statusRecorder: statusRecorder,
|
||||||
checks: checks,
|
checks: checks,
|
||||||
connSemaphore: semaphoregroup.NewSemaphoreGroup(connInitLimit),
|
connSemaphore: semaphoregroup.NewSemaphoreGroup(connInitLimit),
|
||||||
|
flowManager: netflow.NewManager(clientCtx),
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "ios" {
|
if runtime.GOOS == "ios" {
|
||||||
if !fileExists(mobileDep.StateFilePath) {
|
if !fileExists(mobileDep.StateFilePath) {
|
||||||
@@ -266,6 +272,13 @@ func (e *Engine) Stop() error {
|
|||||||
// stop/restore DNS first so dbus and friends don't complain because of a missing interface
|
// stop/restore DNS first so dbus and friends don't complain because of a missing interface
|
||||||
e.stopDNSServer()
|
e.stopDNSServer()
|
||||||
|
|
||||||
|
if e.ingressGatewayMgr != nil {
|
||||||
|
if err := e.ingressGatewayMgr.Close(); err != nil {
|
||||||
|
log.Warnf("failed to cleanup forward rules: %v", err)
|
||||||
|
}
|
||||||
|
e.ingressGatewayMgr = nil
|
||||||
|
}
|
||||||
|
|
||||||
if e.routeManager != nil {
|
if e.routeManager != nil {
|
||||||
e.routeManager.Stop(e.stateManager)
|
e.routeManager.Stop(e.stateManager)
|
||||||
}
|
}
|
||||||
@@ -290,6 +303,8 @@ func (e *Engine) Stop() error {
|
|||||||
return fmt.Errorf("failed to remove all peers: %s", err)
|
return fmt.Errorf("failed to remove all peers: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e.flowManager.Close()
|
||||||
|
|
||||||
if e.cancel != nil {
|
if e.cancel != nil {
|
||||||
e.cancel()
|
e.cancel()
|
||||||
}
|
}
|
||||||
@@ -469,15 +484,15 @@ func (e *Engine) initFirewall() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rosenpassPort := e.rpManager.GetAddress().Port
|
rosenpassPort := e.rpManager.GetAddress().Port
|
||||||
port := manager.Port{Values: []uint16{uint16(rosenpassPort)}}
|
port := firewallManager.Port{Values: []uint16{uint16(rosenpassPort)}}
|
||||||
|
|
||||||
// this rule is static and will be torn down on engine down by the firewall manager
|
// this rule is static and will be torn down on engine down by the firewall manager
|
||||||
if _, err := e.firewall.AddPeerFiltering(
|
if _, err := e.firewall.AddPeerFiltering(
|
||||||
net.IP{0, 0, 0, 0},
|
net.IP{0, 0, 0, 0},
|
||||||
manager.ProtocolUDP,
|
firewallManager.ProtocolUDP,
|
||||||
nil,
|
nil,
|
||||||
&port,
|
&port,
|
||||||
manager.ActionAccept,
|
firewallManager.ActionAccept,
|
||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@@ -505,10 +520,10 @@ func (e *Engine) blockLanAccess() {
|
|||||||
if _, err := e.firewall.AddRouteFiltering(
|
if _, err := e.firewall.AddRouteFiltering(
|
||||||
[]netip.Prefix{v4},
|
[]netip.Prefix{v4},
|
||||||
network,
|
network,
|
||||||
manager.ProtocolALL,
|
firewallManager.ProtocolALL,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
manager.ActionDrop,
|
firewallManager.ActionDrop,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
merr = multierror.Append(merr, fmt.Errorf("add fw rule for network %s: %w", network, err))
|
merr = multierror.Append(merr, fmt.Errorf("add fw rule for network %s: %w", network, err))
|
||||||
}
|
}
|
||||||
@@ -633,25 +648,14 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
|
|||||||
stunTurn = append(stunTurn, e.TURNs...)
|
stunTurn = append(stunTurn, e.TURNs...)
|
||||||
e.stunTurn.Store(stunTurn)
|
e.stunTurn.Store(stunTurn)
|
||||||
|
|
||||||
relayMsg := wCfg.GetRelay()
|
err = e.handleRelayUpdate(wCfg.GetRelay())
|
||||||
if relayMsg != nil {
|
if err != nil {
|
||||||
// when we receive token we expect valid address list too
|
return err
|
||||||
c := &auth.Token{
|
}
|
||||||
Payload: relayMsg.GetTokenPayload(),
|
|
||||||
Signature: relayMsg.GetTokenSignature(),
|
|
||||||
}
|
|
||||||
if err := e.relayManager.UpdateToken(c); err != nil {
|
|
||||||
log.Errorf("failed to update relay token: %v", err)
|
|
||||||
return fmt.Errorf("update relay token: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
e.relayManager.UpdateServerURLs(relayMsg.Urls)
|
err = e.handleFlowUpdate(wCfg.GetFlow())
|
||||||
|
if err != nil {
|
||||||
// Just in case the agent started with an MGM server where the relay was disabled but was later enabled.
|
return fmt.Errorf("handle the flow configuration: %w", err)
|
||||||
// We can ignore all errors because the guard will manage the reconnection retries.
|
|
||||||
_ = e.relayManager.Serve()
|
|
||||||
} else {
|
|
||||||
e.relayManager.UpdateServerURLs(nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo update signal
|
// todo update signal
|
||||||
@@ -682,6 +686,54 @@ func (e *Engine) handleSync(update *mgmProto.SyncResponse) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Engine) handleRelayUpdate(update *mgmProto.RelayConfig) error {
|
||||||
|
if update != nil {
|
||||||
|
// when we receive token we expect valid address list too
|
||||||
|
c := &auth.Token{
|
||||||
|
Payload: update.GetTokenPayload(),
|
||||||
|
Signature: update.GetTokenSignature(),
|
||||||
|
}
|
||||||
|
if err := e.relayManager.UpdateToken(c); err != nil {
|
||||||
|
return fmt.Errorf("update relay token: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
e.relayManager.UpdateServerURLs(update.Urls)
|
||||||
|
|
||||||
|
// Just in case the agent started with an MGM server where the relay was disabled but was later enabled.
|
||||||
|
// We can ignore all errors because the guard will manage the reconnection retries.
|
||||||
|
_ = e.relayManager.Serve()
|
||||||
|
} else {
|
||||||
|
e.relayManager.UpdateServerURLs(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Engine) handleFlowUpdate(config *mgmProto.FlowConfig) error {
|
||||||
|
if config == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
flowConfig, err := toFlowLoggerConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return e.flowManager.Update(flowConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toFlowLoggerConfig(config *mgmProto.FlowConfig) (*types.FlowConfig, error) {
|
||||||
|
if config.GetInterval() == nil {
|
||||||
|
return nil, errors.New("flow interval is nil")
|
||||||
|
}
|
||||||
|
return &types.FlowConfig{
|
||||||
|
Enabled: config.GetEnabled(),
|
||||||
|
URL: config.GetUrl(),
|
||||||
|
TokenPayload: config.GetTokenPayload(),
|
||||||
|
TokenSignature: config.GetTokenSignature(),
|
||||||
|
Interval: config.GetInterval().AsDuration(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// updateChecksIfNew updates checks if there are changes and sync new meta with management
|
// updateChecksIfNew updates checks if there are changes and sync new meta with management
|
||||||
func (e *Engine) updateChecksIfNew(checks []*mgmProto.Checks) error {
|
func (e *Engine) updateChecksIfNew(checks []*mgmProto.Checks) error {
|
||||||
// if checks are equal, we skip the update
|
// if checks are equal, we skip the update
|
||||||
@@ -912,6 +964,11 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
|
|||||||
log.Errorf("failed to update clientRoutes, err: %v", err)
|
log.Errorf("failed to update clientRoutes, err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ingress forward rules
|
||||||
|
if err := e.updateForwardRules(networkMap.GetForwardingRules()); err != nil {
|
||||||
|
log.Errorf("failed to update forward rules, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Debugf("got peers update from Management Service, total peers to connect to = %d", len(networkMap.GetRemotePeers()))
|
log.Debugf("got peers update from Management Service, total peers to connect to = %d", len(networkMap.GetRemotePeers()))
|
||||||
|
|
||||||
e.updateOfflinePeers(networkMap.GetOfflinePeers())
|
e.updateOfflinePeers(networkMap.GetOfflinePeers())
|
||||||
@@ -1482,7 +1539,7 @@ func (e *Engine) GetRouteManager() routemanager.Manager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetFirewallManager returns the firewall manager
|
// GetFirewallManager returns the firewall manager
|
||||||
func (e *Engine) GetFirewallManager() manager.Manager {
|
func (e *Engine) GetFirewallManager() firewallManager.Manager {
|
||||||
return e.firewall
|
return e.firewall
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1770,6 +1827,74 @@ func (e *Engine) Address() (netip.Addr, error) {
|
|||||||
return ip.Unmap(), nil
|
return ip.Unmap(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Engine) updateForwardRules(rules []*mgmProto.ForwardingRule) error {
|
||||||
|
if e.firewall == nil {
|
||||||
|
log.Warn("firewall is disabled, not updating forwarding rules")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rules) == 0 {
|
||||||
|
if e.ingressGatewayMgr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := e.ingressGatewayMgr.Close()
|
||||||
|
e.ingressGatewayMgr = nil
|
||||||
|
e.statusRecorder.SetIngressGwMgr(nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.ingressGatewayMgr == nil {
|
||||||
|
mgr := ingressgw.NewManager(e.firewall)
|
||||||
|
e.ingressGatewayMgr = mgr
|
||||||
|
e.statusRecorder.SetIngressGwMgr(mgr)
|
||||||
|
}
|
||||||
|
|
||||||
|
var merr *multierror.Error
|
||||||
|
forwardingRules := make([]firewallManager.ForwardRule, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
proto, err := convertToFirewallProtocol(rule.GetProtocol())
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("failed to convert protocol '%s': %w", rule.GetProtocol(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
dstPortInfo, err := convertPortInfo(rule.GetDestinationPort())
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("invalid destination port '%v': %w", rule.GetDestinationPort(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
translateIP, err := convertToIP(rule.GetTranslatedAddress())
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("failed to convert translated address '%s': %w", rule.GetTranslatedAddress(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
translatePort, err := convertPortInfo(rule.GetTranslatedPort())
|
||||||
|
if err != nil {
|
||||||
|
merr = multierror.Append(merr, fmt.Errorf("invalid translate port '%v': %w", rule.GetTranslatedPort(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
forwardRule := firewallManager.ForwardRule{
|
||||||
|
Protocol: proto,
|
||||||
|
DestinationPort: *dstPortInfo,
|
||||||
|
TranslatedAddress: translateIP,
|
||||||
|
TranslatedPort: *translatePort,
|
||||||
|
}
|
||||||
|
|
||||||
|
forwardingRules = append(forwardingRules, forwardRule)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Infof("updating forwarding rules: %d", len(forwardingRules))
|
||||||
|
if err := e.ingressGatewayMgr.Update(forwardingRules); err != nil {
|
||||||
|
log.Errorf("failed to update forwarding rules: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nberrors.FormatErrorOrNil(merr)
|
||||||
|
}
|
||||||
|
|
||||||
// isChecksEqual checks if two slices of checks are equal.
|
// isChecksEqual checks if two slices of checks are equal.
|
||||||
func isChecksEqual(checks []*mgmProto.Checks, oChecks []*mgmProto.Checks) bool {
|
func isChecksEqual(checks []*mgmProto.Checks, oChecks []*mgmProto.Checks) bool {
|
||||||
for _, check := range checks {
|
for _, check := range checks {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import (
|
|||||||
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -1433,13 +1434,13 @@ func startManagement(t *testing.T, dataDir, testFile string) (*grpc.Server, stri
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics)
|
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
secretsManager := server.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
secretsManager := server.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
||||||
mgmtServer, err := server.NewServer(context.Background(), config, accountManager, settings.NewManager(store), peersUpdateManager, secretsManager, nil, nil, nil)
|
mgmtServer, err := server.NewServer(context.Background(), config, accountManager, settings.NewManagerMock(), peersUpdateManager, secretsManager, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
107
client/internal/ingressgw/manager.go
Normal file
107
client/internal/ingressgw/manager.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package ingressgw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
nberrors "github.com/netbirdio/netbird/client/errors"
|
||||||
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DNATFirewall interface {
|
||||||
|
AddDNATRule(fwdRule firewall.ForwardRule) (firewall.Rule, error)
|
||||||
|
DeleteDNATRule(rule firewall.Rule) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type RulePair struct {
|
||||||
|
firewall.ForwardRule
|
||||||
|
firewall.Rule
|
||||||
|
}
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
dnatFirewall DNATFirewall
|
||||||
|
|
||||||
|
rules map[string]RulePair // keys is the ID of the ForwardRule
|
||||||
|
rulesMu sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(dnatFirewall DNATFirewall) *Manager {
|
||||||
|
return &Manager{
|
||||||
|
dnatFirewall: dnatFirewall,
|
||||||
|
rules: make(map[string]RulePair),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Manager) Update(forwardRules []firewall.ForwardRule) error {
|
||||||
|
h.rulesMu.Lock()
|
||||||
|
defer h.rulesMu.Unlock()
|
||||||
|
|
||||||
|
var mErr *multierror.Error
|
||||||
|
|
||||||
|
toDelete := make(map[string]RulePair, len(h.rules))
|
||||||
|
for id, r := range h.rules {
|
||||||
|
toDelete[id] = r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process new/updated rules
|
||||||
|
for _, fwdRule := range forwardRules {
|
||||||
|
id := fwdRule.ID()
|
||||||
|
if _, ok := h.rules[id]; ok {
|
||||||
|
delete(toDelete, id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := h.dnatFirewall.AddDNATRule(fwdRule)
|
||||||
|
if err != nil {
|
||||||
|
mErr = multierror.Append(mErr, fmt.Errorf("add forward rule '%s': %v", fwdRule.String(), err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Infof("forward rule has been added '%s'", fwdRule)
|
||||||
|
h.rules[id] = RulePair{
|
||||||
|
ForwardRule: fwdRule,
|
||||||
|
Rule: rule,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove deleted rules
|
||||||
|
for id, rulePair := range toDelete {
|
||||||
|
if err := h.dnatFirewall.DeleteDNATRule(rulePair.Rule); err != nil {
|
||||||
|
mErr = multierror.Append(mErr, fmt.Errorf("failed to delete forward rule '%s': %v", rulePair.ForwardRule.String(), err))
|
||||||
|
}
|
||||||
|
log.Infof("forward rule has been deleted '%s'", rulePair.ForwardRule)
|
||||||
|
delete(h.rules, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nberrors.FormatErrorOrNil(mErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Manager) Close() error {
|
||||||
|
h.rulesMu.Lock()
|
||||||
|
defer h.rulesMu.Unlock()
|
||||||
|
|
||||||
|
log.Infof("clean up all (%d) forward rules", len(h.rules))
|
||||||
|
var mErr *multierror.Error
|
||||||
|
for _, rule := range h.rules {
|
||||||
|
if err := h.dnatFirewall.DeleteDNATRule(rule.Rule); err != nil {
|
||||||
|
mErr = multierror.Append(mErr, fmt.Errorf("failed to delete forward rule '%s': %v", rule, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.rules = make(map[string]RulePair)
|
||||||
|
return nberrors.FormatErrorOrNil(mErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Manager) Rules() []firewall.ForwardRule {
|
||||||
|
h.rulesMu.Lock()
|
||||||
|
defer h.rulesMu.Unlock()
|
||||||
|
|
||||||
|
rules := make([]firewall.ForwardRule, 0, len(h.rules))
|
||||||
|
for _, rulePair := range h.rules {
|
||||||
|
rules = append(rules, rulePair.ForwardRule)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rules
|
||||||
|
}
|
||||||
281
client/internal/ingressgw/manager_test.go
Normal file
281
client/internal/ingressgw/manager_test.go
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
package ingressgw
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ firewall.Rule = (*MocFwRule)(nil)
|
||||||
|
_ DNATFirewall = &MockDNATFirewall{}
|
||||||
|
)
|
||||||
|
|
||||||
|
type MocFwRule struct {
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MocFwRule) ID() string {
|
||||||
|
return string(m.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockDNATFirewall struct {
|
||||||
|
throwError bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockDNATFirewall) AddDNATRule(fwdRule firewall.ForwardRule) (firewall.Rule, error) {
|
||||||
|
if m.throwError {
|
||||||
|
return nil, fmt.Errorf("moc error")
|
||||||
|
}
|
||||||
|
|
||||||
|
fwRule := &MocFwRule{
|
||||||
|
id: fwdRule.ID(),
|
||||||
|
}
|
||||||
|
return fwRule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockDNATFirewall) DeleteDNATRule(rule firewall.Rule) error {
|
||||||
|
if m.throwError {
|
||||||
|
return fmt.Errorf("moc error")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockDNATFirewall) forceToThrowErrors() {
|
||||||
|
m.throwError = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_AddRule(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
|
||||||
|
updates := []firewall.ForwardRule{
|
||||||
|
{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Protocol: firewall.ProtocolUDP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}}
|
||||||
|
|
||||||
|
if err := mgr.Update(updates); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != len(updates) {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_UpdateRule(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleUDP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolUDP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.2"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleUDP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 1 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rules[0].TranslatedAddress.String() != ruleUDP.TranslatedAddress.String() {
|
||||||
|
t.Errorf("unexpected rule: %v", rules[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if rules[0].TranslatedPort.String() != ruleUDP.TranslatedPort.String() {
|
||||||
|
t.Errorf("unexpected rule: %v", rules[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if rules[0].DestinationPort.String() != ruleUDP.DestinationPort.String() {
|
||||||
|
t.Errorf("unexpected rule: %v", rules[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if rules[0].Protocol != ruleUDP.Protocol {
|
||||||
|
t.Errorf("unexpected rule: %v", rules[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_ExtendRules(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleUDP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolUDP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.2"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP, ruleUDP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 2 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_UnderlingError(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleUDP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolUDP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.2"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fw.forceToThrowErrors()
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP, ruleUDP}); err == nil {
|
||||||
|
t.Errorf("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 1 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_Cleanup(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 0 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_DeleteBrokenRule(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
|
||||||
|
// force to throw errors when Add DNAT Rule
|
||||||
|
fw.forceToThrowErrors()
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err == nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 0 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
|
||||||
|
// simulate that to remove a broken rule
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Close(); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestManager_Close(t *testing.T) {
|
||||||
|
fw := &MockDNATFirewall{}
|
||||||
|
mgr := NewManager(fw)
|
||||||
|
|
||||||
|
port, _ := firewall.NewPort(8080)
|
||||||
|
ruleTCP := firewall.ForwardRule{
|
||||||
|
Protocol: firewall.ProtocolTCP,
|
||||||
|
DestinationPort: *port,
|
||||||
|
TranslatedAddress: netip.MustParseAddr("172.16.254.1"),
|
||||||
|
TranslatedPort: *port,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Update([]firewall.ForwardRule{ruleTCP}); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := mgr.Close(); err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := mgr.Rules()
|
||||||
|
if len(rules) != 0 {
|
||||||
|
t.Errorf("unexpected rules count: %d", len(rules))
|
||||||
|
}
|
||||||
|
}
|
||||||
58
client/internal/message_convert.go
Normal file
58
client/internal/message_convert.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
firewallManager "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
|
mgmProto "github.com/netbirdio/netbird/management/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func convertToFirewallProtocol(protocol mgmProto.RuleProtocol) (firewallManager.Protocol, error) {
|
||||||
|
switch protocol {
|
||||||
|
case mgmProto.RuleProtocol_TCP:
|
||||||
|
return firewallManager.ProtocolTCP, nil
|
||||||
|
case mgmProto.RuleProtocol_UDP:
|
||||||
|
return firewallManager.ProtocolUDP, nil
|
||||||
|
case mgmProto.RuleProtocol_ICMP:
|
||||||
|
return firewallManager.ProtocolICMP, nil
|
||||||
|
case mgmProto.RuleProtocol_ALL:
|
||||||
|
return firewallManager.ProtocolALL, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("invalid protocol type: %s", protocol.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertPortInfo(portInfo *mgmProto.PortInfo) (*firewallManager.Port, error) {
|
||||||
|
if portInfo == nil {
|
||||||
|
return nil, errors.New("portInfo cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if portInfo.GetPort() != 0 {
|
||||||
|
return firewallManager.NewPort(int(portInfo.GetPort()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if portInfo.GetRange() != nil {
|
||||||
|
return firewallManager.NewPort(int(portInfo.GetRange().Start), int(portInfo.GetRange().End))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("invalid portInfo: %v", portInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertToIP(rawIP []byte) (netip.Addr, error) {
|
||||||
|
if rawIP == nil {
|
||||||
|
return netip.Addr{}, errors.New("input bytes cannot be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rawIP) != net.IPv4len && len(rawIP) != net.IPv6len {
|
||||||
|
return netip.Addr{}, fmt.Errorf("invalid IP length: %d", len(rawIP))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rawIP) == net.IPv4len {
|
||||||
|
return netip.AddrFrom4([4]byte(rawIP)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return netip.AddrFrom16([16]byte(rawIP)), nil
|
||||||
|
}
|
||||||
113
client/internal/netflow/logger/logger.go
Normal file
113
client/internal/netflow/logger/logger.go
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/store"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type rcvChan chan *types.EventFields
|
||||||
|
type Logger struct {
|
||||||
|
mux sync.Mutex
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
enabled atomic.Bool
|
||||||
|
rcvChan atomic.Pointer[rcvChan]
|
||||||
|
cancelReceiver context.CancelFunc
|
||||||
|
Store types.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context) *Logger {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
return &Logger{
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
Store: store.NewMemoryStore(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) StoreEvent(flowEvent types.EventFields) {
|
||||||
|
if !l.enabled.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c := l.rcvChan.Load()
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case *c <- &flowEvent:
|
||||||
|
default:
|
||||||
|
// todo: we should collect or log on this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Enable() {
|
||||||
|
go l.startReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) startReceiver() {
|
||||||
|
if l.enabled.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l.mux.Lock()
|
||||||
|
ctx, cancel := context.WithCancel(l.ctx)
|
||||||
|
l.cancelReceiver = cancel
|
||||||
|
l.mux.Unlock()
|
||||||
|
|
||||||
|
c := make(rcvChan, 100)
|
||||||
|
l.rcvChan.Swap(&c)
|
||||||
|
l.enabled.Store(true)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Info("flow Memory store receiver stopped")
|
||||||
|
return
|
||||||
|
case eventFields := <-c:
|
||||||
|
id := uuid.NewString()
|
||||||
|
event := types.Event{
|
||||||
|
ID: id,
|
||||||
|
EventFields: *eventFields,
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
}
|
||||||
|
l.Store.StoreEvent(&event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Disable() {
|
||||||
|
l.stop()
|
||||||
|
l.Store.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) stop() {
|
||||||
|
if !l.enabled.Load() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.enabled.Store(false)
|
||||||
|
l.mux.Lock()
|
||||||
|
if l.cancelReceiver != nil {
|
||||||
|
l.cancelReceiver()
|
||||||
|
l.cancelReceiver = nil
|
||||||
|
}
|
||||||
|
l.mux.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) GetEvents() []*types.Event {
|
||||||
|
return l.Store.GetEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Close() {
|
||||||
|
l.stop()
|
||||||
|
l.cancel()
|
||||||
|
}
|
||||||
67
client/internal/netflow/logger/logger_test.go
Normal file
67
client/internal/netflow/logger/logger_test.go
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package logger_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/logger"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStore(t *testing.T) {
|
||||||
|
logger := logger.New(context.Background())
|
||||||
|
logger.Enable()
|
||||||
|
|
||||||
|
event := types.EventFields{
|
||||||
|
FlowID: uuid.New(),
|
||||||
|
Type: types.TypeStart,
|
||||||
|
Direction: types.Ingress,
|
||||||
|
Protocol: 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
wait := func() { time.Sleep(time.Millisecond) }
|
||||||
|
wait()
|
||||||
|
logger.StoreEvent(event)
|
||||||
|
wait()
|
||||||
|
|
||||||
|
allEvents := logger.GetEvents()
|
||||||
|
matched := false
|
||||||
|
for _, e := range allEvents {
|
||||||
|
if e.EventFields.FlowID == event.FlowID {
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
t.Errorf("didn't match any event")
|
||||||
|
}
|
||||||
|
|
||||||
|
// test disable
|
||||||
|
logger.Disable()
|
||||||
|
wait()
|
||||||
|
logger.StoreEvent(event)
|
||||||
|
wait()
|
||||||
|
allEvents = logger.GetEvents()
|
||||||
|
if len(allEvents) != 0 {
|
||||||
|
t.Errorf("expected 0 events, got %d", len(allEvents))
|
||||||
|
}
|
||||||
|
|
||||||
|
// test re-enable
|
||||||
|
logger.Enable()
|
||||||
|
wait()
|
||||||
|
logger.StoreEvent(event)
|
||||||
|
wait()
|
||||||
|
|
||||||
|
allEvents = logger.GetEvents()
|
||||||
|
matched = false
|
||||||
|
for _, e := range allEvents {
|
||||||
|
if e.EventFields.FlowID == event.FlowID {
|
||||||
|
matched = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
t.Errorf("didn't match any event")
|
||||||
|
}
|
||||||
|
}
|
||||||
48
client/internal/netflow/manager.go
Normal file
48
client/internal/netflow/manager.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package netflow
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/logger"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
mux sync.Mutex
|
||||||
|
logger types.FlowLogger
|
||||||
|
flowConfig *types.FlowConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(ctx context.Context) *Manager {
|
||||||
|
return &Manager{
|
||||||
|
logger: logger.New(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Update(update *types.FlowConfig) error {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
if update == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.flowConfig = update
|
||||||
|
|
||||||
|
if update.Enabled {
|
||||||
|
m.logger.Enable()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.logger.Disable()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) Close() {
|
||||||
|
m.logger.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) GetLogger() types.FlowLogger {
|
||||||
|
return m.logger
|
||||||
|
}
|
||||||
48
client/internal/netflow/store/memory.go
Normal file
48
client/internal/netflow/store/memory.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/netflow/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMemoryStore() *Memory {
|
||||||
|
return &Memory{
|
||||||
|
events: make(map[string]*types.Event),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Memory struct {
|
||||||
|
mux sync.Mutex
|
||||||
|
events map[string]*types.Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) StoreEvent(event *types.Event) {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
m.events[event.ID] = event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) Close() {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
m.events = make(map[string]*types.Event)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) GetEvents() []*types.Event {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
events := make([]*types.Event, 0, len(m.events))
|
||||||
|
for _, event := range m.events {
|
||||||
|
events = append(events, event)
|
||||||
|
}
|
||||||
|
return events
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Memory) DeleteEvents(ids []string) {
|
||||||
|
m.mux.Lock()
|
||||||
|
defer m.mux.Unlock()
|
||||||
|
for _, id := range ids {
|
||||||
|
delete(m.events, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
82
client/internal/netflow/types/types.go
Normal file
82
client/internal/netflow/types/types.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Type int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeStart = iota
|
||||||
|
TypeEnd
|
||||||
|
)
|
||||||
|
|
||||||
|
type Direction int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Ingress = iota
|
||||||
|
Egress
|
||||||
|
)
|
||||||
|
|
||||||
|
type Event struct {
|
||||||
|
ID string
|
||||||
|
Timestamp time.Time
|
||||||
|
EventFields
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventFields struct {
|
||||||
|
FlowID uuid.UUID
|
||||||
|
Type Type
|
||||||
|
Direction Direction
|
||||||
|
Protocol uint8
|
||||||
|
SourceIP netip.Addr
|
||||||
|
DestIP netip.Addr
|
||||||
|
SourcePort uint16
|
||||||
|
DestPort uint16
|
||||||
|
ICMPType uint8
|
||||||
|
ICMPCode uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowConfig struct {
|
||||||
|
URL string
|
||||||
|
Interval time.Duration
|
||||||
|
Enabled bool
|
||||||
|
TokenPayload string
|
||||||
|
TokenSignature string
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowManager interface {
|
||||||
|
// FlowConfig handles network map updates
|
||||||
|
Update(update *FlowConfig) error
|
||||||
|
// Close closes the manager
|
||||||
|
Close()
|
||||||
|
// GetLogger returns a flow logger
|
||||||
|
GetLogger() FlowLogger
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowLogger interface {
|
||||||
|
// StoreEvent stores a flow event
|
||||||
|
StoreEvent(flowEvent EventFields)
|
||||||
|
// GetEvents returns all stored events
|
||||||
|
GetEvents() []*Event
|
||||||
|
// Close closes the logger
|
||||||
|
Close()
|
||||||
|
// Enable enables the flow logger receiver
|
||||||
|
Enable()
|
||||||
|
// Disable disables the flow logger receiver
|
||||||
|
Disable()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Store interface {
|
||||||
|
// StoreEvent stores a flow event
|
||||||
|
StoreEvent(event *Event)
|
||||||
|
// GetEvents returns all stored events
|
||||||
|
GetEvents() []*Event
|
||||||
|
// DeleteEvents deletes events from the store
|
||||||
|
DeleteEvents([]string)
|
||||||
|
// Close closes the store
|
||||||
|
Close()
|
||||||
|
}
|
||||||
@@ -14,7 +14,9 @@ import (
|
|||||||
gstatus "google.golang.org/grpc/status"
|
gstatus "google.golang.org/grpc/status"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/iface/configurer"
|
"github.com/netbirdio/netbird/client/iface/configurer"
|
||||||
|
"github.com/netbirdio/netbird/client/internal/ingressgw"
|
||||||
"github.com/netbirdio/netbird/client/internal/relay"
|
"github.com/netbirdio/netbird/client/internal/relay"
|
||||||
"github.com/netbirdio/netbird/client/proto"
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
"github.com/netbirdio/netbird/management/domain"
|
"github.com/netbirdio/netbird/management/domain"
|
||||||
@@ -132,13 +134,14 @@ type NSGroupState struct {
|
|||||||
|
|
||||||
// FullStatus contains the full state held by the Status instance
|
// FullStatus contains the full state held by the Status instance
|
||||||
type FullStatus struct {
|
type FullStatus struct {
|
||||||
Peers []State
|
Peers []State
|
||||||
ManagementState ManagementState
|
ManagementState ManagementState
|
||||||
SignalState SignalState
|
SignalState SignalState
|
||||||
LocalPeerState LocalPeerState
|
LocalPeerState LocalPeerState
|
||||||
RosenpassState RosenpassState
|
RosenpassState RosenpassState
|
||||||
Relays []relay.ProbeResult
|
Relays []relay.ProbeResult
|
||||||
NSGroupStates []NSGroupState
|
NSGroupStates []NSGroupState
|
||||||
|
NumOfForwardingRules int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status holds a state of peers, signal, management connections and relays
|
// Status holds a state of peers, signal, management connections and relays
|
||||||
@@ -171,6 +174,8 @@ type Status struct {
|
|||||||
eventMux sync.RWMutex
|
eventMux sync.RWMutex
|
||||||
eventStreams map[string]chan *proto.SystemEvent
|
eventStreams map[string]chan *proto.SystemEvent
|
||||||
eventQueue *EventQueue
|
eventQueue *EventQueue
|
||||||
|
|
||||||
|
ingressGwMgr *ingressgw.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRecorder returns a new Status instance
|
// NewRecorder returns a new Status instance
|
||||||
@@ -193,6 +198,12 @@ func (d *Status) SetRelayMgr(manager *relayClient.Manager) {
|
|||||||
d.relayMgr = manager
|
d.relayMgr = manager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Status) SetIngressGwMgr(ingressGwMgr *ingressgw.Manager) {
|
||||||
|
d.mux.Lock()
|
||||||
|
defer d.mux.Unlock()
|
||||||
|
d.ingressGwMgr = ingressGwMgr
|
||||||
|
}
|
||||||
|
|
||||||
// ReplaceOfflinePeers replaces
|
// ReplaceOfflinePeers replaces
|
||||||
func (d *Status) ReplaceOfflinePeers(replacement []State) {
|
func (d *Status) ReplaceOfflinePeers(replacement []State) {
|
||||||
d.mux.Lock()
|
d.mux.Lock()
|
||||||
@@ -235,6 +246,18 @@ func (d *Status) GetPeer(peerPubKey string) (State, error) {
|
|||||||
return state, nil
|
return state, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Status) PeerByIP(ip string) (string, bool) {
|
||||||
|
d.mux.Lock()
|
||||||
|
defer d.mux.Unlock()
|
||||||
|
|
||||||
|
for _, state := range d.peers {
|
||||||
|
if state.IP == ip {
|
||||||
|
return state.FQDN, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
// RemovePeer removes peer from Daemon status map
|
// RemovePeer removes peer from Daemon status map
|
||||||
func (d *Status) RemovePeer(peerPubKey string) error {
|
func (d *Status) RemovePeer(peerPubKey string) error {
|
||||||
d.mux.Lock()
|
d.mux.Lock()
|
||||||
@@ -734,6 +757,16 @@ func (d *Status) GetRelayStates() []relay.ProbeResult {
|
|||||||
return append(relayStates, relayState)
|
return append(relayStates, relayState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Status) ForwardingRules() []firewall.ForwardRule {
|
||||||
|
d.mux.Lock()
|
||||||
|
defer d.mux.Unlock()
|
||||||
|
if d.ingressGwMgr == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.ingressGwMgr.Rules()
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Status) GetDNSStates() []NSGroupState {
|
func (d *Status) GetDNSStates() []NSGroupState {
|
||||||
d.mux.Lock()
|
d.mux.Lock()
|
||||||
defer d.mux.Unlock()
|
defer d.mux.Unlock()
|
||||||
@@ -751,11 +784,12 @@ func (d *Status) GetResolvedDomainsStates() map[domain.Domain]ResolvedDomainInfo
|
|||||||
// GetFullStatus gets full status
|
// GetFullStatus gets full status
|
||||||
func (d *Status) GetFullStatus() FullStatus {
|
func (d *Status) GetFullStatus() FullStatus {
|
||||||
fullStatus := FullStatus{
|
fullStatus := FullStatus{
|
||||||
ManagementState: d.GetManagementState(),
|
ManagementState: d.GetManagementState(),
|
||||||
SignalState: d.GetSignalState(),
|
SignalState: d.GetSignalState(),
|
||||||
Relays: d.GetRelayStates(),
|
Relays: d.GetRelayStates(),
|
||||||
RosenpassState: d.GetRosenpassState(),
|
RosenpassState: d.GetRosenpassState(),
|
||||||
NSGroupStates: d.GetDNSStates(),
|
NSGroupStates: d.GetDNSStates(),
|
||||||
|
NumOfForwardingRules: len(d.ForwardingRules()),
|
||||||
}
|
}
|
||||||
|
|
||||||
d.mux.Lock()
|
d.mux.Lock()
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type PKCEAuthProviderConfig struct {
|
|||||||
RedirectURLs []string
|
RedirectURLs []string
|
||||||
// UseIDToken indicates if the id token should be used for authentication
|
// UseIDToken indicates if the id token should be used for authentication
|
||||||
UseIDToken bool
|
UseIDToken bool
|
||||||
//ClientCertPair is used for mTLS authentication to the IDP
|
// ClientCertPair is used for mTLS authentication to the IDP
|
||||||
ClientCertPair *tls.Certificate
|
ClientCertPair *tls.Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ func (c *clientNetwork) recalculateRouteAndUpdatePeerAndSystem(rsn reason) error
|
|||||||
|
|
||||||
// If the chosen route is the same as the current route, do nothing
|
// If the chosen route is the same as the current route, do nothing
|
||||||
if c.currentChosen != nil && c.currentChosen.ID == newChosenID &&
|
if c.currentChosen != nil && c.currentChosen.ID == newChosenID &&
|
||||||
c.currentChosen.IsEqual(c.routes[newChosenID]) {
|
c.currentChosen.Equal(c.routes[newChosenID]) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
client/internal/routemanager/ipfwdstate/ipfwdstate.go
Normal file
51
client/internal/routemanager/ipfwdstate/ipfwdstate.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package ipfwdstate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPForwardingState is a struct that keeps track of the IP forwarding state.
|
||||||
|
// todo: read initial state of the IP forwarding from the system and reset the state based on it
|
||||||
|
type IPForwardingState struct {
|
||||||
|
enabledCounter int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewIPForwardingState() *IPForwardingState {
|
||||||
|
return &IPForwardingState{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPForwardingState) RequestForwarding() error {
|
||||||
|
if f.enabledCounter != 0 {
|
||||||
|
f.enabledCounter++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := systemops.EnableIPForwarding(); err != nil {
|
||||||
|
return fmt.Errorf("failed to enable IP forwarding with sysctl: %w", err)
|
||||||
|
}
|
||||||
|
f.enabledCounter = 1
|
||||||
|
log.Info("IP forwarding enabled")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPForwardingState) ReleaseForwarding() error {
|
||||||
|
if f.enabledCounter == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.enabledCounter > 1 {
|
||||||
|
f.enabledCounter--
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if failed to disable IP forwarding we anyway decrement the counter
|
||||||
|
f.enabledCounter = 0
|
||||||
|
|
||||||
|
// todo call systemops.DisableIPForwarding()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
"github.com/netbirdio/netbird/client/internal/peer"
|
"github.com/netbirdio/netbird/client/internal/peer"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/iface"
|
"github.com/netbirdio/netbird/client/internal/routemanager/iface"
|
||||||
"github.com/netbirdio/netbird/client/internal/routemanager/systemops"
|
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ func (m *serverRouter) updateRoutes(routesMap map[route.ID]*route.Route) error {
|
|||||||
|
|
||||||
for routeID := range m.routes {
|
for routeID := range m.routes {
|
||||||
update, found := routesMap[routeID]
|
update, found := routesMap[routeID]
|
||||||
if !found || !update.IsEqual(m.routes[routeID]) {
|
if !found || !update.Equal(m.routes[routeID]) {
|
||||||
serverRoutesToRemove = append(serverRoutesToRemove, routeID)
|
serverRoutesToRemove = append(serverRoutesToRemove, routeID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,9 +70,6 @@ func (m *serverRouter) updateRoutes(routesMap map[route.ID]*route.Route) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(m.routes) > 0 {
|
if len(m.routes) > 0 {
|
||||||
if err := systemops.EnableIPForwarding(); err != nil {
|
|
||||||
return fmt.Errorf("enable ip forwarding: %w", err)
|
|
||||||
}
|
|
||||||
if err := m.firewall.EnableRouting(); err != nil {
|
if err := m.firewall.EnableRouting(); err != nil {
|
||||||
return fmt.Errorf("enable routing: %w", err)
|
return fmt.Errorf("enable routing: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@ option go_package = "/proto";
|
|||||||
|
|
||||||
package daemon;
|
package daemon;
|
||||||
|
|
||||||
|
message EmptyRequest {}
|
||||||
|
|
||||||
service DaemonService {
|
service DaemonService {
|
||||||
// Login uses setup key to prepare configuration for the daemon.
|
// Login uses setup key to prepare configuration for the daemon.
|
||||||
rpc Login(LoginRequest) returns (LoginResponse) {}
|
rpc Login(LoginRequest) returns (LoginResponse) {}
|
||||||
@@ -37,6 +39,8 @@ service DaemonService {
|
|||||||
// Deselect specific routes
|
// Deselect specific routes
|
||||||
rpc DeselectNetworks(SelectNetworksRequest) returns (SelectNetworksResponse) {}
|
rpc DeselectNetworks(SelectNetworksRequest) returns (SelectNetworksResponse) {}
|
||||||
|
|
||||||
|
rpc ForwardingRules(EmptyRequest) returns (ForwardingRulesResponse) {}
|
||||||
|
|
||||||
// DebugBundle creates a debug bundle
|
// DebugBundle creates a debug bundle
|
||||||
rpc DebugBundle(DebugBundleRequest) returns (DebugBundleResponse) {}
|
rpc DebugBundle(DebugBundleRequest) returns (DebugBundleResponse) {}
|
||||||
|
|
||||||
@@ -267,10 +271,12 @@ message FullStatus {
|
|||||||
repeated PeerState peers = 4;
|
repeated PeerState peers = 4;
|
||||||
repeated RelayState relays = 5;
|
repeated RelayState relays = 5;
|
||||||
repeated NSGroupState dns_servers = 6;
|
repeated NSGroupState dns_servers = 6;
|
||||||
|
int32 NumberOfForwardingRules = 8;
|
||||||
|
|
||||||
repeated SystemEvent events = 7;
|
repeated SystemEvent events = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Networks
|
||||||
message ListNetworksRequest {
|
message ListNetworksRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +297,6 @@ message IPList {
|
|||||||
repeated string ips = 1;
|
repeated string ips = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
message Network {
|
message Network {
|
||||||
string ID = 1;
|
string ID = 1;
|
||||||
string range = 2;
|
string range = 2;
|
||||||
@@ -300,6 +305,33 @@ message Network {
|
|||||||
map<string, IPList> resolvedIPs = 5;
|
map<string, IPList> resolvedIPs = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ForwardingRules
|
||||||
|
message PortInfo {
|
||||||
|
oneof portSelection {
|
||||||
|
uint32 port = 1;
|
||||||
|
Range range = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Range {
|
||||||
|
uint32 start = 1;
|
||||||
|
uint32 end = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ForwardingRule {
|
||||||
|
string protocol = 1;
|
||||||
|
PortInfo destinationPort = 2;
|
||||||
|
string translatedAddress = 3;
|
||||||
|
string translatedHostname = 4;
|
||||||
|
PortInfo translatedPort = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ForwardingRulesResponse {
|
||||||
|
repeated ForwardingRule rules = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DebugBundler
|
||||||
message DebugBundleRequest {
|
message DebugBundleRequest {
|
||||||
bool anonymize = 1;
|
bool anonymize = 1;
|
||||||
string status = 2;
|
string status = 2;
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ type DaemonServiceClient interface {
|
|||||||
SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error)
|
SelectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error)
|
||||||
// Deselect specific routes
|
// Deselect specific routes
|
||||||
DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error)
|
DeselectNetworks(ctx context.Context, in *SelectNetworksRequest, opts ...grpc.CallOption) (*SelectNetworksResponse, error)
|
||||||
|
ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error)
|
||||||
// DebugBundle creates a debug bundle
|
// DebugBundle creates a debug bundle
|
||||||
DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error)
|
DebugBundle(ctx context.Context, in *DebugBundleRequest, opts ...grpc.CallOption) (*DebugBundleResponse, error)
|
||||||
// GetLogLevel gets the log level of the daemon
|
// GetLogLevel gets the log level of the daemon
|
||||||
@@ -145,6 +146,15 @@ func (c *daemonServiceClient) DeselectNetworks(ctx context.Context, in *SelectNe
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *daemonServiceClient) ForwardingRules(ctx context.Context, in *EmptyRequest, opts ...grpc.CallOption) (*ForwardingRulesResponse, error) {
|
||||||
|
out := new(ForwardingRulesResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/ForwardingRules", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
out := new(DebugBundleResponse)
|
out := new(DebugBundleResponse)
|
||||||
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DebugBundle", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/daemon.DaemonService/DebugBundle", in, out, opts...)
|
||||||
@@ -281,6 +291,7 @@ type DaemonServiceServer interface {
|
|||||||
SelectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error)
|
SelectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error)
|
||||||
// Deselect specific routes
|
// Deselect specific routes
|
||||||
DeselectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error)
|
DeselectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error)
|
||||||
|
ForwardingRules(context.Context, *EmptyRequest) (*ForwardingRulesResponse, error)
|
||||||
// DebugBundle creates a debug bundle
|
// DebugBundle creates a debug bundle
|
||||||
DebugBundle(context.Context, *DebugBundleRequest) (*DebugBundleResponse, error)
|
DebugBundle(context.Context, *DebugBundleRequest) (*DebugBundleResponse, error)
|
||||||
// GetLogLevel gets the log level of the daemon
|
// GetLogLevel gets the log level of the daemon
|
||||||
@@ -332,6 +343,9 @@ func (UnimplementedDaemonServiceServer) SelectNetworks(context.Context, *SelectN
|
|||||||
func (UnimplementedDaemonServiceServer) DeselectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error) {
|
func (UnimplementedDaemonServiceServer) DeselectNetworks(context.Context, *SelectNetworksRequest) (*SelectNetworksResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method DeselectNetworks not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method DeselectNetworks not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedDaemonServiceServer) ForwardingRules(context.Context, *EmptyRequest) (*ForwardingRulesResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ForwardingRules not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedDaemonServiceServer) DebugBundle(context.Context, *DebugBundleRequest) (*DebugBundleResponse, error) {
|
func (UnimplementedDaemonServiceServer) DebugBundle(context.Context, *DebugBundleRequest) (*DebugBundleResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method DebugBundle not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method DebugBundle not implemented")
|
||||||
}
|
}
|
||||||
@@ -537,6 +551,24 @@ func _DaemonService_DeselectNetworks_Handler(srv interface{}, ctx context.Contex
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _DaemonService_ForwardingRules_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(EmptyRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DaemonServiceServer).ForwardingRules(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/daemon.DaemonService/ForwardingRules",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DaemonServiceServer).ForwardingRules(ctx, req.(*EmptyRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _DaemonService_DebugBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _DaemonService_DebugBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(DebugBundleRequest)
|
in := new(DebugBundleRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@@ -763,6 +795,10 @@ var DaemonService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "DeselectNetworks",
|
MethodName: "DeselectNetworks",
|
||||||
Handler: _DaemonService_DeselectNetworks_Handler,
|
Handler: _DaemonService_DeselectNetworks_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ForwardingRules",
|
||||||
|
Handler: _DaemonService_ForwardingRules_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "DebugBundle",
|
MethodName: "DebugBundle",
|
||||||
Handler: _DaemonService_DebugBundle_Handler,
|
Handler: _DaemonService_DebugBundle_Handler,
|
||||||
|
|||||||
54
client/server/forwardingrules.go
Normal file
54
client/server/forwardingrules.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
firewall "github.com/netbirdio/netbird/client/firewall/manager"
|
||||||
|
"github.com/netbirdio/netbird/client/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) ForwardingRules(context.Context, *proto.EmptyRequest) (*proto.ForwardingRulesResponse, error) {
|
||||||
|
s.mutex.Lock()
|
||||||
|
defer s.mutex.Unlock()
|
||||||
|
|
||||||
|
rules := s.statusRecorder.ForwardingRules()
|
||||||
|
responseRules := make([]*proto.ForwardingRule, 0, len(rules))
|
||||||
|
for _, rule := range rules {
|
||||||
|
respRule := &proto.ForwardingRule{
|
||||||
|
Protocol: string(rule.Protocol),
|
||||||
|
DestinationPort: portToProto(rule.DestinationPort),
|
||||||
|
TranslatedAddress: rule.TranslatedAddress.String(),
|
||||||
|
TranslatedHostname: s.hostNameByTranslateAddress(rule.TranslatedAddress.String()),
|
||||||
|
TranslatedPort: portToProto(rule.TranslatedPort),
|
||||||
|
}
|
||||||
|
responseRules = append(responseRules, respRule)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.ForwardingRulesResponse{Rules: responseRules}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) hostNameByTranslateAddress(ip string) string {
|
||||||
|
hostName, ok := s.statusRecorder.PeerByIP(ip)
|
||||||
|
if !ok {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
return hostName
|
||||||
|
}
|
||||||
|
|
||||||
|
func portToProto(port firewall.Port) *proto.PortInfo {
|
||||||
|
var portInfo proto.PortInfo
|
||||||
|
|
||||||
|
if !port.IsRange {
|
||||||
|
portInfo.PortSelection = &proto.PortInfo_Port{Port: uint32(port.Values[0])}
|
||||||
|
} else {
|
||||||
|
portInfo.PortSelection = &proto.PortInfo_Range_{
|
||||||
|
Range: &proto.PortInfo_Range{
|
||||||
|
Start: uint32(port.Values[0]),
|
||||||
|
End: uint32(port.Values[1]),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &portInfo
|
||||||
|
}
|
||||||
@@ -810,6 +810,7 @@ func toProtoFullStatus(fullStatus peer.FullStatus) *proto.FullStatus {
|
|||||||
pbFullStatus.LocalPeerState.RosenpassPermissive = fullStatus.RosenpassState.Permissive
|
pbFullStatus.LocalPeerState.RosenpassPermissive = fullStatus.RosenpassState.Permissive
|
||||||
pbFullStatus.LocalPeerState.RosenpassEnabled = fullStatus.RosenpassState.Enabled
|
pbFullStatus.LocalPeerState.RosenpassEnabled = fullStatus.RosenpassState.Enabled
|
||||||
pbFullStatus.LocalPeerState.Networks = maps.Keys(fullStatus.LocalPeerState.Routes)
|
pbFullStatus.LocalPeerState.Networks = maps.Keys(fullStatus.LocalPeerState.Routes)
|
||||||
|
pbFullStatus.NumberOfForwardingRules = int32(fullStatus.NumOfForwardingRules)
|
||||||
|
|
||||||
for _, peerState := range fullStatus.Peers {
|
for _, peerState := range fullStatus.Peers {
|
||||||
pbPeerState := &proto.PeerState{
|
pbPeerState := &proto.PeerState{
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import (
|
|||||||
"go.opentelemetry.io/otel"
|
"go.opentelemetry.io/otel"
|
||||||
|
|
||||||
"github.com/netbirdio/management-integrations/integrations"
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/keepalive"
|
"google.golang.org/grpc/keepalive"
|
||||||
@@ -20,6 +19,7 @@ import (
|
|||||||
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -128,13 +128,13 @@ func startManagement(t *testing.T, signalAddr string, counter *int) (*grpc.Serve
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics)
|
accountManager, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
secretsManager := server.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
secretsManager := server.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
||||||
mgmtServer, err := server.NewServer(context.Background(), config, accountManager, settings.NewManager(store), peersUpdateManager, secretsManager, nil, nil, nil)
|
mgmtServer, err := server.NewServer(context.Background(), config, accountManager, settings.NewManagerMock(), peersUpdateManager, secretsManager, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,21 +80,22 @@ type NsServerGroupStateOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OutputOverview struct {
|
type OutputOverview struct {
|
||||||
Peers PeersStateOutput `json:"peers" yaml:"peers"`
|
Peers PeersStateOutput `json:"peers" yaml:"peers"`
|
||||||
CliVersion string `json:"cliVersion" yaml:"cliVersion"`
|
CliVersion string `json:"cliVersion" yaml:"cliVersion"`
|
||||||
DaemonVersion string `json:"daemonVersion" yaml:"daemonVersion"`
|
DaemonVersion string `json:"daemonVersion" yaml:"daemonVersion"`
|
||||||
ManagementState ManagementStateOutput `json:"management" yaml:"management"`
|
ManagementState ManagementStateOutput `json:"management" yaml:"management"`
|
||||||
SignalState SignalStateOutput `json:"signal" yaml:"signal"`
|
SignalState SignalStateOutput `json:"signal" yaml:"signal"`
|
||||||
Relays RelayStateOutput `json:"relays" yaml:"relays"`
|
Relays RelayStateOutput `json:"relays" yaml:"relays"`
|
||||||
IP string `json:"netbirdIp" yaml:"netbirdIp"`
|
IP string `json:"netbirdIp" yaml:"netbirdIp"`
|
||||||
PubKey string `json:"publicKey" yaml:"publicKey"`
|
PubKey string `json:"publicKey" yaml:"publicKey"`
|
||||||
KernelInterface bool `json:"usesKernelInterface" yaml:"usesKernelInterface"`
|
KernelInterface bool `json:"usesKernelInterface" yaml:"usesKernelInterface"`
|
||||||
FQDN string `json:"fqdn" yaml:"fqdn"`
|
FQDN string `json:"fqdn" yaml:"fqdn"`
|
||||||
RosenpassEnabled bool `json:"quantumResistance" yaml:"quantumResistance"`
|
RosenpassEnabled bool `json:"quantumResistance" yaml:"quantumResistance"`
|
||||||
RosenpassPermissive bool `json:"quantumResistancePermissive" yaml:"quantumResistancePermissive"`
|
RosenpassPermissive bool `json:"quantumResistancePermissive" yaml:"quantumResistancePermissive"`
|
||||||
Networks []string `json:"networks" yaml:"networks"`
|
Networks []string `json:"networks" yaml:"networks"`
|
||||||
NSServerGroups []NsServerGroupStateOutput `json:"dnsServers" yaml:"dnsServers"`
|
NumberOfForwardingRules int `json:"forwardingRules" yaml:"forwardingRules"`
|
||||||
Events []SystemEventOutput `json:"events" yaml:"events"`
|
NSServerGroups []NsServerGroupStateOutput `json:"dnsServers" yaml:"dnsServers"`
|
||||||
|
Events []SystemEventOutput `json:"events" yaml:"events"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}) OutputOverview {
|
func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, statusFilter string, prefixNamesFilter []string, prefixNamesFilterMap map[string]struct{}, ipsFilter map[string]struct{}) OutputOverview {
|
||||||
@@ -118,21 +119,22 @@ func ConvertToStatusOutputOverview(resp *proto.StatusResponse, anon bool, status
|
|||||||
peersOverview := mapPeers(resp.GetFullStatus().GetPeers(), statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter)
|
peersOverview := mapPeers(resp.GetFullStatus().GetPeers(), statusFilter, prefixNamesFilter, prefixNamesFilterMap, ipsFilter)
|
||||||
|
|
||||||
overview := OutputOverview{
|
overview := OutputOverview{
|
||||||
Peers: peersOverview,
|
Peers: peersOverview,
|
||||||
CliVersion: version.NetbirdVersion(),
|
CliVersion: version.NetbirdVersion(),
|
||||||
DaemonVersion: resp.GetDaemonVersion(),
|
DaemonVersion: resp.GetDaemonVersion(),
|
||||||
ManagementState: managementOverview,
|
ManagementState: managementOverview,
|
||||||
SignalState: signalOverview,
|
SignalState: signalOverview,
|
||||||
Relays: relayOverview,
|
Relays: relayOverview,
|
||||||
IP: pbFullStatus.GetLocalPeerState().GetIP(),
|
IP: pbFullStatus.GetLocalPeerState().GetIP(),
|
||||||
PubKey: pbFullStatus.GetLocalPeerState().GetPubKey(),
|
PubKey: pbFullStatus.GetLocalPeerState().GetPubKey(),
|
||||||
KernelInterface: pbFullStatus.GetLocalPeerState().GetKernelInterface(),
|
KernelInterface: pbFullStatus.GetLocalPeerState().GetKernelInterface(),
|
||||||
FQDN: pbFullStatus.GetLocalPeerState().GetFqdn(),
|
FQDN: pbFullStatus.GetLocalPeerState().GetFqdn(),
|
||||||
RosenpassEnabled: pbFullStatus.GetLocalPeerState().GetRosenpassEnabled(),
|
RosenpassEnabled: pbFullStatus.GetLocalPeerState().GetRosenpassEnabled(),
|
||||||
RosenpassPermissive: pbFullStatus.GetLocalPeerState().GetRosenpassPermissive(),
|
RosenpassPermissive: pbFullStatus.GetLocalPeerState().GetRosenpassPermissive(),
|
||||||
Networks: pbFullStatus.GetLocalPeerState().GetNetworks(),
|
Networks: pbFullStatus.GetLocalPeerState().GetNetworks(),
|
||||||
NSServerGroups: mapNSGroups(pbFullStatus.GetDnsServers()),
|
NumberOfForwardingRules: int(pbFullStatus.GetNumberOfForwardingRules()),
|
||||||
Events: mapEvents(pbFullStatus.GetEvents()),
|
NSServerGroups: mapNSGroups(pbFullStatus.GetDnsServers()),
|
||||||
|
Events: mapEvents(pbFullStatus.GetEvents()),
|
||||||
}
|
}
|
||||||
|
|
||||||
if anon {
|
if anon {
|
||||||
@@ -403,6 +405,7 @@ func ParseGeneralSummary(overview OutputOverview, showURL bool, showRelays bool,
|
|||||||
"Interface type: %s\n"+
|
"Interface type: %s\n"+
|
||||||
"Quantum resistance: %s\n"+
|
"Quantum resistance: %s\n"+
|
||||||
"Networks: %s\n"+
|
"Networks: %s\n"+
|
||||||
|
"Forwarding rules: %d\n"+
|
||||||
"Peers count: %s\n",
|
"Peers count: %s\n",
|
||||||
fmt.Sprintf("%s/%s%s", goos, goarch, goarm),
|
fmt.Sprintf("%s/%s%s", goos, goarch, goarm),
|
||||||
overview.DaemonVersion,
|
overview.DaemonVersion,
|
||||||
@@ -416,6 +419,7 @@ func ParseGeneralSummary(overview OutputOverview, showURL bool, showRelays bool,
|
|||||||
interfaceTypeString,
|
interfaceTypeString,
|
||||||
rosenpassEnabledStatus,
|
rosenpassEnabledStatus,
|
||||||
networks,
|
networks,
|
||||||
|
overview.NumberOfForwardingRules,
|
||||||
peersCountString,
|
peersCountString,
|
||||||
)
|
)
|
||||||
return summary
|
return summary
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ func TestParsingToJSON(t *testing.T) {
|
|||||||
"networks": [
|
"networks": [
|
||||||
"10.10.0.0/24"
|
"10.10.0.0/24"
|
||||||
],
|
],
|
||||||
|
"forwardingRules": 0,
|
||||||
"dnsServers": [
|
"dnsServers": [
|
||||||
{
|
{
|
||||||
"servers": [
|
"servers": [
|
||||||
@@ -467,6 +468,7 @@ quantumResistance: false
|
|||||||
quantumResistancePermissive: false
|
quantumResistancePermissive: false
|
||||||
networks:
|
networks:
|
||||||
- 10.10.0.0/24
|
- 10.10.0.0/24
|
||||||
|
forwardingRules: 0
|
||||||
dnsServers:
|
dnsServers:
|
||||||
- servers:
|
- servers:
|
||||||
- 8.8.8.8:53
|
- 8.8.8.8:53
|
||||||
@@ -547,6 +549,7 @@ NetBird IP: 192.168.178.100/16
|
|||||||
Interface type: Kernel
|
Interface type: Kernel
|
||||||
Quantum resistance: false
|
Quantum resistance: false
|
||||||
Networks: 10.10.0.0/24
|
Networks: 10.10.0.0/24
|
||||||
|
Forwarding rules: 0
|
||||||
Peers count: 2/2 Connected
|
Peers count: 2/2 Connected
|
||||||
`, lastConnectionUpdate1, lastHandshake1, lastConnectionUpdate2, lastHandshake2, runtime.GOOS, runtime.GOARCH, overview.CliVersion)
|
`, lastConnectionUpdate1, lastHandshake1, lastConnectionUpdate2, lastHandshake2, runtime.GOOS, runtime.GOARCH, overview.CliVersion)
|
||||||
|
|
||||||
@@ -568,6 +571,7 @@ NetBird IP: 192.168.178.100/16
|
|||||||
Interface type: Kernel
|
Interface type: Kernel
|
||||||
Quantum resistance: false
|
Quantum resistance: false
|
||||||
Networks: 10.10.0.0/24
|
Networks: 10.10.0.0/24
|
||||||
|
Forwarding rules: 0
|
||||||
Peers count: 2/2 Connected
|
Peers count: 2/2 Connected
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
691
flow/proto/flow.pb.go
Normal file
691
flow/proto/flow.pb.go
Normal file
@@ -0,0 +1,691 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.26.0
|
||||||
|
// protoc v3.21.9
|
||||||
|
// source: flow.proto
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Flow event types
|
||||||
|
type Type int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
Type_TYPE_UNKNOWN Type = 0
|
||||||
|
Type_TYPE_START Type = 1
|
||||||
|
Type_TYPE_END Type = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for Type.
|
||||||
|
var (
|
||||||
|
Type_name = map[int32]string{
|
||||||
|
0: "TYPE_UNKNOWN",
|
||||||
|
1: "TYPE_START",
|
||||||
|
2: "TYPE_END",
|
||||||
|
}
|
||||||
|
Type_value = map[string]int32{
|
||||||
|
"TYPE_UNKNOWN": 0,
|
||||||
|
"TYPE_START": 1,
|
||||||
|
"TYPE_END": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x Type) Enum() *Type {
|
||||||
|
p := new(Type)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Type) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Type) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_flow_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Type) Type() protoreflect.EnumType {
|
||||||
|
return &file_flow_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Type) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Type.Descriptor instead.
|
||||||
|
func (Type) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flow direction
|
||||||
|
type Direction int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
Direction_DIRECTION_UNKNOWN Direction = 0
|
||||||
|
Direction_INGRESS Direction = 1
|
||||||
|
Direction_EGRESS Direction = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for Direction.
|
||||||
|
var (
|
||||||
|
Direction_name = map[int32]string{
|
||||||
|
0: "DIRECTION_UNKNOWN",
|
||||||
|
1: "INGRESS",
|
||||||
|
2: "EGRESS",
|
||||||
|
}
|
||||||
|
Direction_value = map[string]int32{
|
||||||
|
"DIRECTION_UNKNOWN": 0,
|
||||||
|
"INGRESS": 1,
|
||||||
|
"EGRESS": 2,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x Direction) Enum() *Direction {
|
||||||
|
p := new(Direction)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Direction) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Direction) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_flow_proto_enumTypes[1].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Direction) Type() protoreflect.EnumType {
|
||||||
|
return &file_flow_proto_enumTypes[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Direction) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Direction.Descriptor instead.
|
||||||
|
func (Direction) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowEvent struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Unique client event identifier
|
||||||
|
EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"`
|
||||||
|
// Unique client flow session identifier
|
||||||
|
FlowId string `protobuf:"bytes,2,opt,name=flow_id,json=flowId,proto3" json:"flow_id,omitempty"`
|
||||||
|
// When the event occurred
|
||||||
|
Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||||
|
// Public key of the sending peer
|
||||||
|
PublicKey []byte `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||||
|
EventFields *EventFields `protobuf:"bytes,5,opt,name=event_fields,json=eventFields,proto3" json:"event_fields,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) Reset() {
|
||||||
|
*x = FlowEvent{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_flow_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FlowEvent) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *FlowEvent) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_flow_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use FlowEvent.ProtoReflect.Descriptor instead.
|
||||||
|
func (*FlowEvent) Descriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) GetEventId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.EventId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) GetFlowId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.FlowId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) GetTimestamp() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.Timestamp
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) GetPublicKey() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.PublicKey
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEvent) GetEventFields() *EventFields {
|
||||||
|
if x != nil {
|
||||||
|
return x.EventFields
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowEventAck struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Unique client event identifier that has been ack'ed
|
||||||
|
EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEventAck) Reset() {
|
||||||
|
*x = FlowEventAck{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_flow_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEventAck) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*FlowEventAck) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *FlowEventAck) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_flow_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use FlowEventAck.ProtoReflect.Descriptor instead.
|
||||||
|
func (*FlowEventAck) Descriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *FlowEventAck) GetEventId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.EventId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventFields struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// Event type
|
||||||
|
Type Type `protobuf:"varint,1,opt,name=type,proto3,enum=flow.Type" json:"type,omitempty"`
|
||||||
|
// Initiating traffic direction
|
||||||
|
Direction Direction `protobuf:"varint,2,opt,name=direction,proto3,enum=flow.Direction" json:"direction,omitempty"`
|
||||||
|
// IP protocol number
|
||||||
|
Protocol uint32 `protobuf:"varint,3,opt,name=protocol,proto3" json:"protocol,omitempty"`
|
||||||
|
// Source IP address
|
||||||
|
SourceIp []byte `protobuf:"bytes,4,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"`
|
||||||
|
// Destination IP address
|
||||||
|
DestIp []byte `protobuf:"bytes,5,opt,name=dest_ip,json=destIp,proto3" json:"dest_ip,omitempty"`
|
||||||
|
// Layer 4 -specific information
|
||||||
|
//
|
||||||
|
// Types that are assignable to ConnectionInfo:
|
||||||
|
//
|
||||||
|
// *EventFields_PortInfo
|
||||||
|
// *EventFields_IcmpInfo
|
||||||
|
ConnectionInfo isEventFields_ConnectionInfo `protobuf_oneof:"connection_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) Reset() {
|
||||||
|
*x = EventFields{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_flow_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EventFields) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *EventFields) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_flow_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use EventFields.ProtoReflect.Descriptor instead.
|
||||||
|
func (*EventFields) Descriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetType() Type {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return Type_TYPE_UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetDirection() Direction {
|
||||||
|
if x != nil {
|
||||||
|
return x.Direction
|
||||||
|
}
|
||||||
|
return Direction_DIRECTION_UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetProtocol() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Protocol
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetSourceIp() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.SourceIp
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetDestIp() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.DestIp
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *EventFields) GetConnectionInfo() isEventFields_ConnectionInfo {
|
||||||
|
if m != nil {
|
||||||
|
return m.ConnectionInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetPortInfo() *PortInfo {
|
||||||
|
if x, ok := x.GetConnectionInfo().(*EventFields_PortInfo); ok {
|
||||||
|
return x.PortInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *EventFields) GetIcmpInfo() *ICMPInfo {
|
||||||
|
if x, ok := x.GetConnectionInfo().(*EventFields_IcmpInfo); ok {
|
||||||
|
return x.IcmpInfo
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type isEventFields_ConnectionInfo interface {
|
||||||
|
isEventFields_ConnectionInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventFields_PortInfo struct {
|
||||||
|
// TCP/UDP port information
|
||||||
|
PortInfo *PortInfo `protobuf:"bytes,6,opt,name=port_info,json=portInfo,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventFields_IcmpInfo struct {
|
||||||
|
// ICMP type and code
|
||||||
|
IcmpInfo *ICMPInfo `protobuf:"bytes,7,opt,name=icmp_info,json=icmpInfo,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*EventFields_PortInfo) isEventFields_ConnectionInfo() {}
|
||||||
|
|
||||||
|
func (*EventFields_IcmpInfo) isEventFields_ConnectionInfo() {}
|
||||||
|
|
||||||
|
// TCP/UDP port information
|
||||||
|
type PortInfo struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
SourcePort uint32 `protobuf:"varint,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty"`
|
||||||
|
DestPort uint32 `protobuf:"varint,2,opt,name=dest_port,json=destPort,proto3" json:"dest_port,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PortInfo) Reset() {
|
||||||
|
*x = PortInfo{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_flow_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PortInfo) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PortInfo) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *PortInfo) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_flow_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use PortInfo.ProtoReflect.Descriptor instead.
|
||||||
|
func (*PortInfo) Descriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PortInfo) GetSourcePort() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.SourcePort
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *PortInfo) GetDestPort() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DestPort
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICMP message information
|
||||||
|
type ICMPInfo struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
IcmpType uint32 `protobuf:"varint,1,opt,name=icmp_type,json=icmpType,proto3" json:"icmp_type,omitempty"`
|
||||||
|
IcmpCode uint32 `protobuf:"varint,2,opt,name=icmp_code,json=icmpCode,proto3" json:"icmp_code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ICMPInfo) Reset() {
|
||||||
|
*x = ICMPInfo{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_flow_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ICMPInfo) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ICMPInfo) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ICMPInfo) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_flow_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ICMPInfo.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ICMPInfo) Descriptor() ([]byte, []int) {
|
||||||
|
return file_flow_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ICMPInfo) GetIcmpType() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.IcmpType
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ICMPInfo) GetIcmpCode() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.IcmpCode
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_flow_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_flow_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x0a, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x66, 0x6c,
|
||||||
|
0x6f, 0x77, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x22, 0xce, 0x01, 0x0a, 0x09, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e,
|
||||||
|
0x74, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07,
|
||||||
|
0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66,
|
||||||
|
0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||||
|
0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||||
|
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
||||||
|
0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12,
|
||||||
|
0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20,
|
||||||
|
0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x34,
|
||||||
|
0x0a, 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x18, 0x05,
|
||||||
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x45, 0x76, 0x65, 0x6e,
|
||||||
|
0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x46, 0x69,
|
||||||
|
0x65, 0x6c, 0x64, 0x73, 0x22, 0x29, 0x0a, 0x0c, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e,
|
||||||
|
0x74, 0x41, 0x63, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64,
|
||||||
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22,
|
||||||
|
0x9f, 0x02, 0x0a, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x12,
|
||||||
|
0x1e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0a, 0x2e,
|
||||||
|
0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||||
|
0x2d, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
||||||
|
0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74,
|
||||||
|
0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a,
|
||||||
|
0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
|
||||||
|
0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x6f,
|
||||||
|
0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x73,
|
||||||
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x65, 0x73, 0x74, 0x5f,
|
||||||
|
0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x64, 0x65, 0x73, 0x74, 0x49, 0x70,
|
||||||
|
0x12, 0x2d, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49,
|
||||||
|
0x6e, 0x66, 0x6f, 0x48, 0x00, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12,
|
||||||
|
0x2d, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x49, 0x43, 0x4d, 0x50, 0x49, 0x6e,
|
||||||
|
0x66, 0x6f, 0x48, 0x00, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x11,
|
||||||
|
0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x66,
|
||||||
|
0x6f, 0x22, 0x48, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a,
|
||||||
|
0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x0d, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1b,
|
||||||
|
0x0a, 0x09, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
|
0x0d, 0x52, 0x08, 0x64, 0x65, 0x73, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x44, 0x0a, 0x08, 0x49,
|
||||||
|
0x43, 0x4d, 0x50, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f,
|
||||||
|
0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70,
|
||||||
|
0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x63, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x64,
|
||||||
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x69, 0x63, 0x6d, 0x70, 0x43, 0x6f, 0x64,
|
||||||
|
0x65, 0x2a, 0x36, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50,
|
||||||
|
0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54,
|
||||||
|
0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x54,
|
||||||
|
0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x02, 0x2a, 0x3b, 0x0a, 0x09, 0x44, 0x69, 0x72,
|
||||||
|
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x15, 0x0a, 0x11, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54,
|
||||||
|
0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a,
|
||||||
|
0x07, 0x49, 0x4e, 0x47, 0x52, 0x45, 0x53, 0x53, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x47,
|
||||||
|
0x52, 0x45, 0x53, 0x53, 0x10, 0x02, 0x32, 0x42, 0x0a, 0x0b, 0x46, 0x6c, 0x6f, 0x77, 0x53, 0x65,
|
||||||
|
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12,
|
||||||
|
0x0f, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||||
|
0x1a, 0x12, 0x2e, 0x66, 0x6c, 0x6f, 0x77, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x45, 0x76, 0x65, 0x6e,
|
||||||
|
0x74, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_flow_proto_rawDescOnce sync.Once
|
||||||
|
file_flow_proto_rawDescData = file_flow_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_flow_proto_rawDescGZIP() []byte {
|
||||||
|
file_flow_proto_rawDescOnce.Do(func() {
|
||||||
|
file_flow_proto_rawDescData = protoimpl.X.CompressGZIP(file_flow_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_flow_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_flow_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
|
var file_flow_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
|
var file_flow_proto_goTypes = []interface{}{
|
||||||
|
(Type)(0), // 0: flow.Type
|
||||||
|
(Direction)(0), // 1: flow.Direction
|
||||||
|
(*FlowEvent)(nil), // 2: flow.FlowEvent
|
||||||
|
(*FlowEventAck)(nil), // 3: flow.FlowEventAck
|
||||||
|
(*EventFields)(nil), // 4: flow.EventFields
|
||||||
|
(*PortInfo)(nil), // 5: flow.PortInfo
|
||||||
|
(*ICMPInfo)(nil), // 6: flow.ICMPInfo
|
||||||
|
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
|
||||||
|
}
|
||||||
|
var file_flow_proto_depIdxs = []int32{
|
||||||
|
7, // 0: flow.FlowEvent.timestamp:type_name -> google.protobuf.Timestamp
|
||||||
|
4, // 1: flow.FlowEvent.event_fields:type_name -> flow.EventFields
|
||||||
|
0, // 2: flow.EventFields.type:type_name -> flow.Type
|
||||||
|
1, // 3: flow.EventFields.direction:type_name -> flow.Direction
|
||||||
|
5, // 4: flow.EventFields.port_info:type_name -> flow.PortInfo
|
||||||
|
6, // 5: flow.EventFields.icmp_info:type_name -> flow.ICMPInfo
|
||||||
|
2, // 6: flow.FlowService.Events:input_type -> flow.FlowEvent
|
||||||
|
3, // 7: flow.FlowService.Events:output_type -> flow.FlowEventAck
|
||||||
|
7, // [7:8] is the sub-list for method output_type
|
||||||
|
6, // [6:7] is the sub-list for method input_type
|
||||||
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
|
0, // [0:6] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_flow_proto_init() }
|
||||||
|
func file_flow_proto_init() {
|
||||||
|
if File_flow_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_flow_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*FlowEvent); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_flow_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*FlowEventAck); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_flow_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*EventFields); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_flow_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*PortInfo); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_flow_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ICMPInfo); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_flow_proto_msgTypes[2].OneofWrappers = []interface{}{
|
||||||
|
(*EventFields_PortInfo)(nil),
|
||||||
|
(*EventFields_IcmpInfo)(nil),
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_flow_proto_rawDesc,
|
||||||
|
NumEnums: 2,
|
||||||
|
NumMessages: 5,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_flow_proto_goTypes,
|
||||||
|
DependencyIndexes: file_flow_proto_depIdxs,
|
||||||
|
EnumInfos: file_flow_proto_enumTypes,
|
||||||
|
MessageInfos: file_flow_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_flow_proto = out.File
|
||||||
|
file_flow_proto_rawDesc = nil
|
||||||
|
file_flow_proto_goTypes = nil
|
||||||
|
file_flow_proto_depIdxs = nil
|
||||||
|
}
|
||||||
85
flow/proto/flow.proto
Normal file
85
flow/proto/flow.proto
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
|
option go_package = "/proto";
|
||||||
|
|
||||||
|
package flow;
|
||||||
|
|
||||||
|
service FlowService {
|
||||||
|
// Client to receiver streams of events and acknowledgements
|
||||||
|
rpc Events(stream FlowEvent) returns (stream FlowEventAck) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowEvent {
|
||||||
|
// Unique client event identifier
|
||||||
|
string event_id = 1;
|
||||||
|
|
||||||
|
// Unique client flow session identifier
|
||||||
|
string flow_id = 2;
|
||||||
|
|
||||||
|
// When the event occurred
|
||||||
|
google.protobuf.Timestamp timestamp = 3;
|
||||||
|
|
||||||
|
// Public key of the sending peer
|
||||||
|
bytes public_key = 4;
|
||||||
|
|
||||||
|
EventFields event_fields = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FlowEventAck {
|
||||||
|
// Unique client event identifier that has been ack'ed
|
||||||
|
string event_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EventFields {
|
||||||
|
// Event type
|
||||||
|
Type type = 1;
|
||||||
|
|
||||||
|
// Initiating traffic direction
|
||||||
|
Direction direction = 2;
|
||||||
|
|
||||||
|
// IP protocol number
|
||||||
|
uint32 protocol = 3;
|
||||||
|
|
||||||
|
// Source IP address
|
||||||
|
bytes source_ip = 4;
|
||||||
|
|
||||||
|
// Destination IP address
|
||||||
|
bytes dest_ip = 5;
|
||||||
|
|
||||||
|
// Layer 4 -specific information
|
||||||
|
oneof connection_info {
|
||||||
|
// TCP/UDP port information
|
||||||
|
PortInfo port_info = 6;
|
||||||
|
|
||||||
|
// ICMP type and code
|
||||||
|
ICMPInfo icmp_info = 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flow event types
|
||||||
|
enum Type {
|
||||||
|
TYPE_UNKNOWN = 0;
|
||||||
|
TYPE_START = 1;
|
||||||
|
TYPE_END = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flow direction
|
||||||
|
enum Direction {
|
||||||
|
DIRECTION_UNKNOWN = 0;
|
||||||
|
INGRESS = 1;
|
||||||
|
EGRESS = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCP/UDP port information
|
||||||
|
message PortInfo {
|
||||||
|
uint32 source_port = 1;
|
||||||
|
uint32 dest_port = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ICMP message information
|
||||||
|
message ICMPInfo {
|
||||||
|
uint32 icmp_type = 1;
|
||||||
|
uint32 icmp_code = 2;
|
||||||
|
}
|
||||||
135
flow/proto/flow_grpc.pb.go
Normal file
135
flow/proto/flow_grpc.pb.go
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
// FlowServiceClient is the client API for FlowService service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type FlowServiceClient interface {
|
||||||
|
// Client to receiver streams of events and acknowledgements
|
||||||
|
Events(ctx context.Context, opts ...grpc.CallOption) (FlowService_EventsClient, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type flowServiceClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFlowServiceClient(cc grpc.ClientConnInterface) FlowServiceClient {
|
||||||
|
return &flowServiceClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *flowServiceClient) Events(ctx context.Context, opts ...grpc.CallOption) (FlowService_EventsClient, error) {
|
||||||
|
stream, err := c.cc.NewStream(ctx, &FlowService_ServiceDesc.Streams[0], "/flow.FlowService/Events", opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x := &flowServiceEventsClient{stream}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowService_EventsClient interface {
|
||||||
|
Send(*FlowEvent) error
|
||||||
|
Recv() (*FlowEventAck, error)
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type flowServiceEventsClient struct {
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *flowServiceEventsClient) Send(m *FlowEvent) error {
|
||||||
|
return x.ClientStream.SendMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *flowServiceEventsClient) Recv() (*FlowEventAck, error) {
|
||||||
|
m := new(FlowEventAck)
|
||||||
|
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlowServiceServer is the server API for FlowService service.
|
||||||
|
// All implementations must embed UnimplementedFlowServiceServer
|
||||||
|
// for forward compatibility
|
||||||
|
type FlowServiceServer interface {
|
||||||
|
// Client to receiver streams of events and acknowledgements
|
||||||
|
Events(FlowService_EventsServer) error
|
||||||
|
mustEmbedUnimplementedFlowServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedFlowServiceServer must be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedFlowServiceServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedFlowServiceServer) Events(FlowService_EventsServer) error {
|
||||||
|
return status.Errorf(codes.Unimplemented, "method Events not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedFlowServiceServer) mustEmbedUnimplementedFlowServiceServer() {}
|
||||||
|
|
||||||
|
// UnsafeFlowServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to FlowServiceServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeFlowServiceServer interface {
|
||||||
|
mustEmbedUnimplementedFlowServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterFlowServiceServer(s grpc.ServiceRegistrar, srv FlowServiceServer) {
|
||||||
|
s.RegisterService(&FlowService_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _FlowService_Events_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
|
return srv.(FlowServiceServer).Events(&flowServiceEventsServer{stream})
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowService_EventsServer interface {
|
||||||
|
Send(*FlowEventAck) error
|
||||||
|
Recv() (*FlowEvent, error)
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type flowServiceEventsServer struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *flowServiceEventsServer) Send(m *FlowEventAck) error {
|
||||||
|
return x.ServerStream.SendMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *flowServiceEventsServer) Recv() (*FlowEvent, error) {
|
||||||
|
m := new(FlowEvent)
|
||||||
|
if err := x.ServerStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlowService_ServiceDesc is the grpc.ServiceDesc for FlowService service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var FlowService_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "flow.FlowService",
|
||||||
|
HandlerType: (*FlowServiceServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{},
|
||||||
|
Streams: []grpc.StreamDesc{
|
||||||
|
{
|
||||||
|
StreamName: "Events",
|
||||||
|
Handler: _FlowService_Events_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
ClientStreams: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Metadata: "flow.proto",
|
||||||
|
}
|
||||||
17
flow/proto/generate.sh
Executable file
17
flow/proto/generate.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if ! which realpath > /dev/null 2>&1
|
||||||
|
then
|
||||||
|
echo realpath is not installed
|
||||||
|
echo run: brew install coreutils
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
old_pwd=$(pwd)
|
||||||
|
script_path=$(dirname $(realpath "$0"))
|
||||||
|
cd "$script_path"
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
||||||
|
protoc -I ./ ./flow.proto --go_out=../ --go-grpc_out=../
|
||||||
|
cd "$old_pwd"
|
||||||
50
go.mod
50
go.mod
@@ -24,8 +24,8 @@ require (
|
|||||||
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
|
golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||||
google.golang.org/grpc v1.70.0
|
google.golang.org/grpc v1.64.1
|
||||||
google.golang.org/protobuf v1.36.4
|
google.golang.org/protobuf v1.34.2
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ require (
|
|||||||
github.com/miekg/dns v1.1.59
|
github.com/miekg/dns v1.1.59
|
||||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||||
github.com/nadoo/ipset v0.5.0
|
github.com/nadoo/ipset v0.5.0
|
||||||
github.com/netbirdio/management-integrations/integrations v0.0.0-20250220173202-e599d83524fc
|
github.com/netbirdio/management-integrations/integrations v0.0.0-20250226165736-0ac3dc443266
|
||||||
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20241010133937-e0df50df217d
|
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20241010133937-e0df50df217d
|
||||||
github.com/okta/okta-sdk-golang/v2 v2.18.0
|
github.com/okta/okta-sdk-golang/v2 v2.18.0
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
@@ -76,27 +76,27 @@ require (
|
|||||||
github.com/shirou/gopsutil/v3 v3.24.4
|
github.com/shirou/gopsutil/v3 v3.24.4
|
||||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/testcontainers/testcontainers-go v0.31.0
|
github.com/testcontainers/testcontainers-go v0.31.0
|
||||||
github.com/testcontainers/testcontainers-go/modules/mysql v0.31.0
|
github.com/testcontainers/testcontainers-go/modules/mysql v0.31.0
|
||||||
github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0
|
github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0
|
||||||
github.com/things-go/go-socks5 v0.0.4
|
github.com/things-go/go-socks5 v0.0.4
|
||||||
github.com/yusufpapurcu/wmi v1.2.4
|
github.com/yusufpapurcu/wmi v1.2.4
|
||||||
github.com/zcalusic/sysinfo v1.1.3
|
github.com/zcalusic/sysinfo v1.1.3
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0
|
||||||
go.opentelemetry.io/otel v1.34.0
|
go.opentelemetry.io/otel v1.26.0
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.48.0
|
go.opentelemetry.io/otel/exporters/prometheus v0.48.0
|
||||||
go.opentelemetry.io/otel/metric v1.34.0
|
go.opentelemetry.io/otel/metric v1.26.0
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0
|
go.opentelemetry.io/otel/sdk/metric v1.26.0
|
||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
goauthentik.io/api/v3 v3.2023051.3
|
goauthentik.io/api/v3 v3.2023051.3
|
||||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||||
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a
|
golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a
|
||||||
golang.org/x/net v0.34.0
|
golang.org/x/net v0.33.0
|
||||||
golang.org/x/oauth2 v0.26.0
|
golang.org/x/oauth2 v0.19.0
|
||||||
golang.org/x/sync v0.10.0
|
golang.org/x/sync v0.10.0
|
||||||
golang.org/x/term v0.28.0
|
golang.org/x/term v0.28.0
|
||||||
google.golang.org/api v0.220.0
|
google.golang.org/api v0.177.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
gorm.io/driver/mysql v1.5.7
|
gorm.io/driver/mysql v1.5.7
|
||||||
gorm.io/driver/postgres v1.5.7
|
gorm.io/driver/postgres v1.5.7
|
||||||
@@ -106,9 +106,9 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.14.1 // indirect
|
cloud.google.com/go/auth v0.3.0 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||||
dario.cat/mergo v1.0.0 // indirect
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||||
@@ -151,7 +151,7 @@ require (
|
|||||||
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
|
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
|
||||||
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
|
github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
@@ -160,11 +160,12 @@ require (
|
|||||||
github.com/go-text/render v0.2.0 // indirect
|
github.com/go-text/render v0.2.0 // indirect
|
||||||
github.com/go-text/typesetting v0.2.0 // indirect
|
github.com/go-text/typesetting v0.2.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.7 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
|
||||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
@@ -220,19 +221,20 @@ require (
|
|||||||
github.com/vishvananda/netns v0.0.4 // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
github.com/yuin/goldmark v1.7.1 // indirect
|
github.com/yuin/goldmark v1.7.1 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.26.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
go.opentelemetry.io/otel/trace v1.26.0 // indirect
|
||||||
go.uber.org/mock v0.4.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/image v0.18.0 // indirect
|
golang.org/x/image v0.18.0 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
golang.org/x/mod v0.17.0 // indirect
|
||||||
golang.org/x/text v0.21.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/time v0.10.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434 // indirect
|
||||||
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
|
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 // indirect
|
||||||
|
|||||||
111
go.sum
111
go.sum
@@ -18,10 +18,10 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW
|
|||||||
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
|
||||||
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
|
||||||
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
|
||||||
cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0=
|
cloud.google.com/go/auth v0.3.0 h1:PRyzEpGfx/Z9e8+lHsbkoUVXD0gnu4MNmm7Gp8TQNIs=
|
||||||
cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM=
|
cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
|
cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
|
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
@@ -29,8 +29,8 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM
|
|||||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
@@ -225,8 +225,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+
|
|||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
@@ -263,12 +263,14 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
|||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/glog v1.2.3 h1:oDTdz9f5VGVVNGu/Q7UXKWYsD0873HXLHdJUNBsSEKM=
|
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||||
github.com/golang/glog v1.2.3/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
@@ -343,18 +345,18 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe
|
|||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
|
||||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
|
||||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
github.com/gopacket/gopacket v1.1.1 h1:zbx9F9d6A7sWNkFKrvMBZTfGgxFoY4NgUudFVVHMfcw=
|
github.com/gopacket/gopacket v1.1.1 h1:zbx9F9d6A7sWNkFKrvMBZTfGgxFoY4NgUudFVVHMfcw=
|
||||||
github.com/gopacket/gopacket v1.1.1/go.mod h1:HavMeONEl7W9036of9LbSWoonqhH7HA1+ZRO+rMIvFs=
|
github.com/gopacket/gopacket v1.1.1/go.mod h1:HavMeONEl7W9036of9LbSWoonqhH7HA1+ZRO+rMIvFs=
|
||||||
@@ -527,8 +529,8 @@ github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944 h1:TDtJKmM6S
|
|||||||
github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944/go.mod h1:sHA6TRxjQ6RLbnI+3R4DZo2Eseg/iKiPRfNmcuNySVQ=
|
github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944/go.mod h1:sHA6TRxjQ6RLbnI+3R4DZo2Eseg/iKiPRfNmcuNySVQ=
|
||||||
github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e h1:PURA50S8u4mF6RrkYYCAvvPCixhqqEiEy3Ej6avh04c=
|
github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e h1:PURA50S8u4mF6RrkYYCAvvPCixhqqEiEy3Ej6avh04c=
|
||||||
github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e/go.mod h1:YMLU7qbKfVjmEv7EoZPIVEI+kNYxWCdPK3VS0BU+U4Q=
|
github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e/go.mod h1:YMLU7qbKfVjmEv7EoZPIVEI+kNYxWCdPK3VS0BU+U4Q=
|
||||||
github.com/netbirdio/management-integrations/integrations v0.0.0-20250220173202-e599d83524fc h1:18xvjOy2tZVIK7rihNpf9DF/3mAiljYKWaQlWa9vJgI=
|
github.com/netbirdio/management-integrations/integrations v0.0.0-20250226165736-0ac3dc443266 h1:z7yibtn9dqDpT/UhLYY5bF4ELK5H06d4iaUoteRCfwE=
|
||||||
github.com/netbirdio/management-integrations/integrations v0.0.0-20250220173202-e599d83524fc/go.mod h1:izUUs1NT7ja+PwSX3kJ7ox8Kkn478tboBJSjL4kU6J0=
|
github.com/netbirdio/management-integrations/integrations v0.0.0-20250226165736-0ac3dc443266/go.mod h1:smsjbLWt5BUYXRKFwbBvUvembwYYXxryY+EHXKnG5KQ=
|
||||||
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502 h1:3tHlFmhTdX9axERMVN63dqyFqnvuD+EMJHzM7mNGON8=
|
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502 h1:3tHlFmhTdX9axERMVN63dqyFqnvuD+EMJHzM7mNGON8=
|
||||||
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
|
github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
|
||||||
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20241010133937-e0df50df217d h1:bRq5TKgC7Iq20pDiuC54yXaWnAVeS5PdGpSokFTlR28=
|
github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20241010133937-e0df50df217d h1:bRq5TKgC7Iq20pDiuC54yXaWnAVeS5PdGpSokFTlR28=
|
||||||
@@ -615,8 +617,8 @@ github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KW
|
|||||||
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
github.com/rs/cors v1.8.0 h1:P2KMzcFwrPoSjkF1WLRPsp3UMLyql8L4v9hQpVeK5so=
|
||||||
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM=
|
||||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
|
||||||
@@ -681,11 +683,11 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/testcontainers/testcontainers-go v0.31.0 h1:W0VwIhcEVhRflwL9as3dhY6jXjVCA27AkmbnZ+UTh3U=
|
github.com/testcontainers/testcontainers-go v0.31.0 h1:W0VwIhcEVhRflwL9as3dhY6jXjVCA27AkmbnZ+UTh3U=
|
||||||
github.com/testcontainers/testcontainers-go v0.31.0/go.mod h1:D2lAoA0zUFiSY+eAflqK5mcUx/A5hrrORaEQrd0SefI=
|
github.com/testcontainers/testcontainers-go v0.31.0/go.mod h1:D2lAoA0zUFiSY+eAflqK5mcUx/A5hrrORaEQrd0SefI=
|
||||||
@@ -737,28 +739,28 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
|||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
|
||||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
|
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc=
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s=
|
go.opentelemetry.io/otel/exporters/prometheus v0.48.0 h1:sBQe3VNGUjY9IKWQC6z2lNqa5iGbDSxhs60ABwK4y0s=
|
||||||
go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o=
|
go.opentelemetry.io/otel/exporters/prometheus v0.48.0/go.mod h1:DtrbMzoZWwQHyrQmCfLam5DZbnmorsGbOtTbYHycU5o=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
go.opentelemetry.io/otel/sdk v1.26.0 h1:Y7bumHf5tAiDlRYFmGqetNcLaVUZmh4iYfmGxtmz7F8=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
go.opentelemetry.io/otel/sdk v1.26.0/go.mod h1:0p8MXpqLeJ0pzcszQQN4F0S5FVjBLgypeGSngLsmirs=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
go.opentelemetry.io/otel/sdk/metric v1.26.0 h1:cWSks5tfriHPdWFnl+qpX3P681aAYqlZHcAyHw5aU9Y=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
go.opentelemetry.io/otel/sdk/metric v1.26.0/go.mod h1:ClMFFknnThJCksebJwz7KIyEDHO+nTB6gK8obLy8RyE=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
@@ -883,8 +885,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
|||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -898,8 +900,8 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ
|
|||||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||||
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
|
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
|
||||||
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -1017,8 +1019,8 @@ golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
|||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -1112,8 +1114,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR
|
|||||||
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
|
||||||
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
|
||||||
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
|
||||||
google.golang.org/api v0.220.0 h1:3oMI4gdBgB72WFVwE1nerDD8W3HUOS4kypK6rRLbGns=
|
google.golang.org/api v0.177.0 h1:8a0p/BbPa65GlqGWtUKxot4p0TV8OGOfyTjtmkXNXmk=
|
||||||
google.golang.org/api v0.220.0/go.mod h1:26ZAlY6aN/8WgpCzjPNy18QpYaz7Zgg1h0qe1GkZEmY=
|
google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
@@ -1162,11 +1164,10 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D
|
|||||||
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
|
||||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
|
||||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434 h1:OpXbo8JnN8+jZGPrL4SSfaDjSCjupr8lXyBAbexEm/U=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
|
google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287 h1:J1H9f+LEdWAfHcez/4cvaVBox7cOYT+IU6rgqj5x++8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250127172529-29210b9bc287/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@@ -1187,8 +1188,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
|
|||||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
|
||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -1203,8 +1204,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
|||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/client/system"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/system"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
@@ -72,13 +72,13 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics)
|
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secretsManager := mgmt.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
secretsManager := mgmt.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
||||||
mgmtServer, err := mgmt.NewServer(context.Background(), config, accountManager, settings.NewManager(store), peersUpdateManager, secretsManager, nil, nil, nil)
|
mgmtServer, err := mgmt.NewServer(context.Background(), config, accountManager, settings.NewManagerMock(), peersUpdateManager, secretsManager, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
||||||
|
|
||||||
"github.com/netbirdio/management-integrations/integrations"
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
|
"github.com/netbirdio/netbird/management/server/peers"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/encryption"
|
"github.com/netbirdio/netbird/encryption"
|
||||||
"github.com/netbirdio/netbird/formatter"
|
"github.com/netbirdio/netbird/formatter"
|
||||||
@@ -199,8 +200,16 @@ var (
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to initialize integrated peer validator: %v", err)
|
return fmt.Errorf("failed to initialize integrated peer validator: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userManager := users.NewManager(store)
|
||||||
|
extraSettingsManager := integrations.NewManager()
|
||||||
|
settingsManager := settings.NewManager(store, userManager, extraSettingsManager)
|
||||||
|
permissionsManager := permissions.NewManager(userManager, settingsManager)
|
||||||
|
peersManager := peers.NewManager(store, permissionsManager)
|
||||||
|
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)
|
dnsDomain, eventStore, geo, userDeleteFromIDPEnabled, integratedPeerValidator, appMetrics, proxyController, settingsManager)
|
||||||
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)
|
||||||
}
|
}
|
||||||
@@ -261,15 +270,14 @@ var (
|
|||||||
config.HttpConfig.AuthUserIDClaim,
|
config.HttpConfig.AuthUserIDClaim,
|
||||||
config.GetAuthAudiences(),
|
config.GetAuthAudiences(),
|
||||||
config.HttpConfig.IdpSignKeyRefreshEnabled)
|
config.HttpConfig.IdpSignKeyRefreshEnabled)
|
||||||
userManager := users.NewManager(store)
|
|
||||||
settingsManager := settings.NewManager(store)
|
|
||||||
permissionsManager := permissions.NewManager(userManager, settingsManager)
|
|
||||||
groupsManager := groups.NewManager(store, permissionsManager, accountManager)
|
groupsManager := groups.NewManager(store, permissionsManager, accountManager)
|
||||||
resourcesManager := resources.NewManager(store, permissionsManager, groupsManager, accountManager)
|
resourcesManager := resources.NewManager(store, permissionsManager, groupsManager, accountManager)
|
||||||
routersManager := routers.NewManager(store, permissionsManager, accountManager)
|
routersManager := routers.NewManager(store, permissionsManager, accountManager)
|
||||||
networksManager := networks.NewManager(store, permissionsManager, resourcesManager, routersManager, accountManager)
|
networksManager := networks.NewManager(store, permissionsManager, resourcesManager, routersManager, accountManager)
|
||||||
|
|
||||||
httpAPIHandler, err := nbhttp.NewAPIHandler(ctx, accountManager, networksManager, resourcesManager, routersManager, groupsManager, geo, authManager, appMetrics, config, integratedPeerValidator)
|
httpAPIHandler, err := nbhttp.NewAPIHandler(ctx, accountManager, networksManager, resourcesManager, routersManager, groupsManager, geo, authManager, appMetrics, integratedPeerValidator, proxyController, permissionsManager, peersManager, settingsManager)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed creating HTTP API handler: %v", err)
|
return fmt.Errorf("failed creating HTTP API handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package domain
|
package domain
|
||||||
|
|
||||||
import "strings"
|
import (
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
type List []Domain
|
type List []Domain
|
||||||
|
|
||||||
@@ -60,6 +63,27 @@ func (d List) PunycodeString() string {
|
|||||||
return strings.Join(d.ToPunycodeList(), ", ")
|
return strings.Join(d.ToPunycodeList(), ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d List) Equal(domains List) bool {
|
||||||
|
if len(d) != len(domains) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(d, func(i, j int) bool {
|
||||||
|
return d[i] < d[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
sort.Slice(domains, func(i, j int) bool {
|
||||||
|
return domains[i] < domains[j]
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, domain := range d {
|
||||||
|
if domain != domains[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// FromStringList creates a DomainList from a slice of string.
|
// FromStringList creates a DomainList from a slice of string.
|
||||||
func FromStringList(s []string) (List, error) {
|
func FromStringList(s []string) (List, error) {
|
||||||
var dl List
|
var dl List
|
||||||
|
|||||||
49
management/domain/list_test.go
Normal file
49
management/domain/list_test.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package domain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_EqualReturnsTrueForIdenticalLists(t *testing.T) {
|
||||||
|
list1 := List{"domain1", "domain2", "domain3"}
|
||||||
|
list2 := List{"domain1", "domain2", "domain3"}
|
||||||
|
|
||||||
|
assert.True(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualReturnsFalseForDifferentLengths(t *testing.T) {
|
||||||
|
list1 := List{"domain1", "domain2"}
|
||||||
|
list2 := List{"domain1", "domain2", "domain3"}
|
||||||
|
|
||||||
|
assert.False(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualReturnsFalseForDifferentElements(t *testing.T) {
|
||||||
|
list1 := List{"domain1", "domain2", "domain3"}
|
||||||
|
list2 := List{"domain1", "domain4", "domain3"}
|
||||||
|
|
||||||
|
assert.False(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualReturnsTrueForUnsortedIdenticalLists(t *testing.T) {
|
||||||
|
list1 := List{"domain3", "domain1", "domain2"}
|
||||||
|
list2 := List{"domain1", "domain2", "domain3"}
|
||||||
|
|
||||||
|
assert.True(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualReturnsFalseForEmptyAndNonEmptyList(t *testing.T) {
|
||||||
|
list1 := List{}
|
||||||
|
list2 := List{"domain1"}
|
||||||
|
|
||||||
|
assert.False(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualReturnsTrueForBothEmptyLists(t *testing.T) {
|
||||||
|
list1 := List{}
|
||||||
|
list2 := List{}
|
||||||
|
|
||||||
|
assert.True(t, list1.Equal(list2))
|
||||||
|
}
|
||||||
@@ -14,4 +14,4 @@ cd "$script_path"
|
|||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
|
||||||
protoc -I ./ ./management.proto --go_out=../ --go-grpc_out=../
|
protoc -I ./ ./management.proto --go_out=../ --go-grpc_out=../
|
||||||
cd "$old_pwd"
|
cd "$old_pwd"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "google/protobuf/duration.proto";
|
||||||
|
|
||||||
option go_package = "/proto";
|
option go_package = "/proto";
|
||||||
|
|
||||||
@@ -191,6 +192,8 @@ message NetbirdConfig {
|
|||||||
HostConfig signal = 3;
|
HostConfig signal = 3;
|
||||||
|
|
||||||
RelayConfig relay = 4;
|
RelayConfig relay = 4;
|
||||||
|
|
||||||
|
FlowConfig flow = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostConfig describes connection properties of some server (e.g. STUN, Signal, Management)
|
// HostConfig describes connection properties of some server (e.g. STUN, Signal, Management)
|
||||||
@@ -214,6 +217,14 @@ message RelayConfig {
|
|||||||
string tokenSignature = 3;
|
string tokenSignature = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message FlowConfig {
|
||||||
|
string url = 1;
|
||||||
|
string tokenPayload = 2;
|
||||||
|
string tokenSignature = 3;
|
||||||
|
google.protobuf.Duration interval = 4;
|
||||||
|
bool enabled = 5;
|
||||||
|
}
|
||||||
|
|
||||||
// ProtectedHostConfig is similar to HostConfig but has additional user and password
|
// ProtectedHostConfig is similar to HostConfig but has additional user and password
|
||||||
// Mostly used for TURN servers
|
// Mostly used for TURN servers
|
||||||
message ProtectedHostConfig {
|
message ProtectedHostConfig {
|
||||||
@@ -274,6 +285,8 @@ message NetworkMap {
|
|||||||
|
|
||||||
// RoutesFirewallRulesIsEmpty indicates whether RouteFirewallRule array is empty or not to bypass protobuf null and empty array equality.
|
// RoutesFirewallRulesIsEmpty indicates whether RouteFirewallRule array is empty or not to bypass protobuf null and empty array equality.
|
||||||
bool routesFirewallRulesIsEmpty = 11;
|
bool routesFirewallRulesIsEmpty = 11;
|
||||||
|
|
||||||
|
repeated ForwardingRule forwardingRules = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemotePeerConfig represents a configuration of a remote peer.
|
// RemotePeerConfig represents a configuration of a remote peer.
|
||||||
@@ -483,3 +496,17 @@ message RouteFirewallRule {
|
|||||||
uint32 customProtocol = 8;
|
uint32 customProtocol = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ForwardingRule {
|
||||||
|
// Protocol of the forwarding rule
|
||||||
|
RuleProtocol protocol = 1;
|
||||||
|
|
||||||
|
// portInfo is the ingress destination port information, where the traffic arrives in the gateway node
|
||||||
|
PortInfo destinationPort = 2;
|
||||||
|
|
||||||
|
// IP address of the translated address (remote peer) to send traffic to
|
||||||
|
// todo type pending
|
||||||
|
bytes translatedAddress = 3;
|
||||||
|
|
||||||
|
// Translated port information, where the traffic should be forwarded to
|
||||||
|
PortInfo translatedPort = 4;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -22,14 +21,16 @@ import (
|
|||||||
"golang.org/x/exp/maps"
|
"golang.org/x/exp/maps"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/domain"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||||
"github.com/netbirdio/netbird/management/server/idp"
|
"github.com/netbirdio/netbird/management/server/idp"
|
||||||
"github.com/netbirdio/netbird/management/server/integrated_validator"
|
"github.com/netbirdio/netbird/management/server/integrations/integrated_validator"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -48,104 +49,11 @@ const (
|
|||||||
|
|
||||||
type userLoggedInOnce bool
|
type userLoggedInOnce bool
|
||||||
|
|
||||||
type ExternalCacheManager cache.CacheInterface[*idp.UserData]
|
|
||||||
|
|
||||||
func cacheEntryExpiration() time.Duration {
|
func cacheEntryExpiration() time.Duration {
|
||||||
r := rand.Intn(int(CacheExpirationMax.Milliseconds()-CacheExpirationMin.Milliseconds())) + int(CacheExpirationMin.Milliseconds())
|
r := rand.Intn(int(CacheExpirationMax.Milliseconds()-CacheExpirationMin.Milliseconds())) + int(CacheExpirationMin.Milliseconds())
|
||||||
return time.Duration(r) * time.Millisecond
|
return time.Duration(r) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountManager interface {
|
|
||||||
GetOrCreateAccountByUser(ctx context.Context, userId, domain string) (*types.Account, error)
|
|
||||||
GetAccount(ctx context.Context, accountID string) (*types.Account, error)
|
|
||||||
CreateSetupKey(ctx context.Context, accountID string, keyName string, keyType types.SetupKeyType, expiresIn time.Duration,
|
|
||||||
autoGroups []string, usageLimit int, userID string, ephemeral bool, allowExtraDNSLabels bool) (*types.SetupKey, error)
|
|
||||||
SaveSetupKey(ctx context.Context, accountID string, key *types.SetupKey, userID string) (*types.SetupKey, error)
|
|
||||||
CreateUser(ctx context.Context, accountID, initiatorUserID string, key *types.UserInfo) (*types.UserInfo, error)
|
|
||||||
DeleteUser(ctx context.Context, accountID, initiatorUserID string, targetUserID string) error
|
|
||||||
DeleteRegularUsers(ctx context.Context, accountID, initiatorUserID string, targetUserIDs []string, userInfos map[string]*types.UserInfo) error
|
|
||||||
InviteUser(ctx context.Context, accountID string, initiatorUserID string, targetUserID string) error
|
|
||||||
ListSetupKeys(ctx context.Context, accountID, userID string) ([]*types.SetupKey, error)
|
|
||||||
SaveUser(ctx context.Context, accountID, initiatorUserID string, update *types.User) (*types.UserInfo, error)
|
|
||||||
SaveOrAddUser(ctx context.Context, accountID, initiatorUserID string, update *types.User, addIfNotExists bool) (*types.UserInfo, error)
|
|
||||||
SaveOrAddUsers(ctx context.Context, accountID, initiatorUserID string, updates []*types.User, addIfNotExists bool) ([]*types.UserInfo, error)
|
|
||||||
GetSetupKey(ctx context.Context, accountID, userID, keyID string) (*types.SetupKey, error)
|
|
||||||
GetAccountByID(ctx context.Context, accountID string, userID string) (*types.Account, error)
|
|
||||||
AccountExists(ctx context.Context, accountID string) (bool, error)
|
|
||||||
GetAccountIDByUserID(ctx context.Context, userID, domain string) (string, error)
|
|
||||||
GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error)
|
|
||||||
DeleteAccount(ctx context.Context, accountID, userID string) error
|
|
||||||
GetUserByID(ctx context.Context, id string) (*types.User, error)
|
|
||||||
GetUserFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
|
||||||
ListUsers(ctx context.Context, accountID string) ([]*types.User, error)
|
|
||||||
GetPeers(ctx context.Context, accountID, userID string) ([]*nbpeer.Peer, error)
|
|
||||||
MarkPeerConnected(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string) error
|
|
||||||
DeletePeer(ctx context.Context, accountID, peerID, userID string) error
|
|
||||||
UpdatePeer(ctx context.Context, accountID, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, error)
|
|
||||||
GetNetworkMap(ctx context.Context, peerID string) (*types.NetworkMap, error)
|
|
||||||
GetPeerNetwork(ctx context.Context, peerID string) (*types.Network, error)
|
|
||||||
AddPeer(ctx context.Context, setupKey, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
|
||||||
CreatePAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenName string, expiresIn int) (*types.PersonalAccessTokenGenerated, error)
|
|
||||||
DeletePAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenID string) error
|
|
||||||
GetPAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenID string) (*types.PersonalAccessToken, error)
|
|
||||||
GetAllPATs(ctx context.Context, accountID string, initiatorUserID string, targetUserID string) ([]*types.PersonalAccessToken, error)
|
|
||||||
GetUsersFromAccount(ctx context.Context, accountID, userID string) (map[string]*types.UserInfo, error)
|
|
||||||
GetGroup(ctx context.Context, accountId, groupID, userID string) (*types.Group, error)
|
|
||||||
GetAllGroups(ctx context.Context, accountID, userID string) ([]*types.Group, error)
|
|
||||||
GetGroupByName(ctx context.Context, groupName, accountID string) (*types.Group, error)
|
|
||||||
SaveGroup(ctx context.Context, accountID, userID string, group *types.Group) error
|
|
||||||
SaveGroups(ctx context.Context, accountID, userID string, newGroups []*types.Group) error
|
|
||||||
DeleteGroup(ctx context.Context, accountId, userId, groupID string) error
|
|
||||||
DeleteGroups(ctx context.Context, accountId, userId string, groupIDs []string) error
|
|
||||||
GroupAddPeer(ctx context.Context, accountId, groupID, peerID string) error
|
|
||||||
GroupDeletePeer(ctx context.Context, accountId, groupID, peerID string) error
|
|
||||||
GetPeerGroups(ctx context.Context, accountID, peerID string) ([]*types.Group, error)
|
|
||||||
GetPolicy(ctx context.Context, accountID, policyID, userID string) (*types.Policy, error)
|
|
||||||
SavePolicy(ctx context.Context, accountID, userID string, policy *types.Policy) (*types.Policy, error)
|
|
||||||
DeletePolicy(ctx context.Context, accountID, policyID, userID string) error
|
|
||||||
ListPolicies(ctx context.Context, accountID, userID string) ([]*types.Policy, error)
|
|
||||||
GetRoute(ctx context.Context, accountID string, routeID route.ID, userID string) (*route.Route, error)
|
|
||||||
CreateRoute(ctx context.Context, accountID string, prefix netip.Prefix, networkType route.NetworkType, domains domain.List, peerID string, peerGroupIDs []string, description string, netID route.NetID, masquerade bool, metric int, groups, accessControlGroupIDs []string, enabled bool, userID string, keepRoute bool) (*route.Route, error)
|
|
||||||
SaveRoute(ctx context.Context, accountID, userID string, route *route.Route) error
|
|
||||||
DeleteRoute(ctx context.Context, accountID string, routeID route.ID, userID string) error
|
|
||||||
ListRoutes(ctx context.Context, accountID, userID string) ([]*route.Route, error)
|
|
||||||
GetNameServerGroup(ctx context.Context, accountID, userID, nsGroupID string) (*nbdns.NameServerGroup, error)
|
|
||||||
CreateNameServerGroup(ctx context.Context, accountID string, name, description string, nameServerList []nbdns.NameServer, groups []string, primary bool, domains []string, enabled bool, userID string, searchDomainsEnabled bool) (*nbdns.NameServerGroup, error)
|
|
||||||
SaveNameServerGroup(ctx context.Context, accountID, userID string, nsGroupToSave *nbdns.NameServerGroup) error
|
|
||||||
DeleteNameServerGroup(ctx context.Context, accountID, nsGroupID, userID string) error
|
|
||||||
ListNameServerGroups(ctx context.Context, accountID string, userID string) ([]*nbdns.NameServerGroup, error)
|
|
||||||
GetDNSDomain() string
|
|
||||||
StoreEvent(ctx context.Context, initiatorID, targetID, accountID string, activityID activity.ActivityDescriber, meta map[string]any)
|
|
||||||
GetEvents(ctx context.Context, accountID, userID string) ([]*activity.Event, error)
|
|
||||||
GetDNSSettings(ctx context.Context, accountID string, userID string) (*types.DNSSettings, error)
|
|
||||||
SaveDNSSettings(ctx context.Context, accountID string, userID string, dnsSettingsToSave *types.DNSSettings) error
|
|
||||||
GetPeer(ctx context.Context, accountID, peerID, userID string) (*nbpeer.Peer, error)
|
|
||||||
UpdateAccountSettings(ctx context.Context, accountID, userID string, newSettings *types.Settings) (*types.Account, error)
|
|
||||||
LoginPeer(ctx context.Context, login PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) // used by peer gRPC API
|
|
||||||
SyncPeer(ctx context.Context, sync PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) // used by peer gRPC API
|
|
||||||
GetAllConnectedPeers() (map[string]struct{}, error)
|
|
||||||
HasConnectedChannel(peerID string) bool
|
|
||||||
GetExternalCacheManager() ExternalCacheManager
|
|
||||||
GetPostureChecks(ctx context.Context, accountID, postureChecksID, userID string) (*posture.Checks, error)
|
|
||||||
SavePostureChecks(ctx context.Context, accountID, userID string, postureChecks *posture.Checks) (*posture.Checks, error)
|
|
||||||
DeletePostureChecks(ctx context.Context, accountID, postureChecksID, userID string) error
|
|
||||||
ListPostureChecks(ctx context.Context, accountID, userID string) ([]*posture.Checks, error)
|
|
||||||
GetIdpManager() idp.Manager
|
|
||||||
UpdateIntegratedValidatorGroups(ctx context.Context, accountID string, userID string, groups []string) error
|
|
||||||
GroupValidation(ctx context.Context, accountId string, groups []string) (bool, error)
|
|
||||||
GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error)
|
|
||||||
SyncAndMarkPeer(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
|
||||||
OnPeerDisconnected(ctx context.Context, accountID string, peerPubKey string) error
|
|
||||||
SyncPeerMeta(ctx context.Context, peerPubKey string, meta nbpeer.PeerSystemMeta) error
|
|
||||||
FindExistingPostureCheck(accountID string, checks *posture.ChecksDefinition) (*posture.Checks, error)
|
|
||||||
GetAccountIDForPeerKey(ctx context.Context, peerKey string) (string, error)
|
|
||||||
GetAccountSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error)
|
|
||||||
DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error
|
|
||||||
UpdateAccountPeers(ctx context.Context, accountID string)
|
|
||||||
BuildUserInfosForAccount(ctx context.Context, accountID, initiatorUserID string, accountUsers []*types.User) (map[string]*types.UserInfo, error)
|
|
||||||
SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type DefaultAccountManager struct {
|
type DefaultAccountManager struct {
|
||||||
Store store.Store
|
Store store.Store
|
||||||
// cacheMux and cacheLoading helps to make sure that only a single cache reload runs at a time per accountID
|
// cacheMux and cacheLoading helps to make sure that only a single cache reload runs at a time per accountID
|
||||||
@@ -155,13 +63,16 @@ type DefaultAccountManager struct {
|
|||||||
peersUpdateManager *PeersUpdateManager
|
peersUpdateManager *PeersUpdateManager
|
||||||
idpManager idp.Manager
|
idpManager idp.Manager
|
||||||
cacheManager cache.CacheInterface[[]*idp.UserData]
|
cacheManager cache.CacheInterface[[]*idp.UserData]
|
||||||
externalCacheManager ExternalCacheManager
|
externalCacheManager account.ExternalCacheManager
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
eventStore activity.Store
|
eventStore activity.Store
|
||||||
geo geolocation.Geolocation
|
geo geolocation.Geolocation
|
||||||
|
|
||||||
requestBuffer *AccountRequestBuffer
|
requestBuffer *AccountRequestBuffer
|
||||||
|
|
||||||
|
proxyController port_forwarding.Controller
|
||||||
|
settingsManager settings.Manager
|
||||||
|
|
||||||
// singleAccountMode indicates whether the instance has a single account.
|
// singleAccountMode indicates whether the instance has a single account.
|
||||||
// If true, then every new user will end up under the same account.
|
// If true, then every new user will end up under the same account.
|
||||||
// This value will be set to false if management service has more than one account.
|
// This value will be set to false if management service has more than one account.
|
||||||
@@ -245,6 +156,8 @@ func BuildManager(
|
|||||||
userDeleteFromIDPEnabled bool,
|
userDeleteFromIDPEnabled bool,
|
||||||
integratedPeerValidator integrated_validator.IntegratedValidator,
|
integratedPeerValidator integrated_validator.IntegratedValidator,
|
||||||
metrics telemetry.AppMetrics,
|
metrics telemetry.AppMetrics,
|
||||||
|
proxyController port_forwarding.Controller,
|
||||||
|
settingsManager settings.Manager,
|
||||||
) (*DefaultAccountManager, error) {
|
) (*DefaultAccountManager, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -267,6 +180,8 @@ func BuildManager(
|
|||||||
integratedPeerValidator: integratedPeerValidator,
|
integratedPeerValidator: integratedPeerValidator,
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
requestBuffer: NewAccountRequestBuffer(ctx, store),
|
requestBuffer: NewAccountRequestBuffer(ctx, store),
|
||||||
|
proxyController: proxyController,
|
||||||
|
settingsManager: settingsManager,
|
||||||
}
|
}
|
||||||
accountsCounter, err := store.GetAccountsCounter(ctx)
|
accountsCounter, err := store.GetAccountsCounter(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -312,7 +227,7 @@ func BuildManager(
|
|||||||
return am, nil
|
return am, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *DefaultAccountManager) GetExternalCacheManager() ExternalCacheManager {
|
func (am *DefaultAccountManager) GetExternalCacheManager() account.ExternalCacheManager {
|
||||||
return am.externalCacheManager
|
return am.externalCacheManager
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,6 +316,11 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = am.settingsManager.UpdateExtraSettings(ctx, accountID, newSettings.Extra)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if updateAccountPeers {
|
if updateAccountPeers {
|
||||||
go am.UpdateAccountPeers(ctx, accountID)
|
go am.UpdateAccountPeers(ctx, accountID)
|
||||||
}
|
}
|
||||||
@@ -1471,7 +1391,7 @@ func (am *DefaultAccountManager) SyncAndMarkPeer(ctx context.Context, accountID
|
|||||||
peerUnlock := am.Store.AcquireWriteLockByUID(ctx, peerPubKey)
|
peerUnlock := am.Store.AcquireWriteLockByUID(ctx, peerPubKey)
|
||||||
defer peerUnlock()
|
defer peerUnlock()
|
||||||
|
|
||||||
peer, netMap, postureChecks, err := am.SyncPeer(ctx, PeerSync{WireGuardPubKey: peerPubKey, Meta: meta}, accountID)
|
peer, netMap, postureChecks, err := am.SyncPeer(ctx, account.PeerSync{WireGuardPubKey: peerPubKey, Meta: meta}, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, fmt.Errorf("error syncing peer: %w", err)
|
return nil, nil, nil, fmt.Errorf("error syncing peer: %w", err)
|
||||||
}
|
}
|
||||||
@@ -1511,7 +1431,7 @@ func (am *DefaultAccountManager) SyncPeerMeta(ctx context.Context, peerPubKey st
|
|||||||
unlockPeer := am.Store.AcquireWriteLockByUID(ctx, peerPubKey)
|
unlockPeer := am.Store.AcquireWriteLockByUID(ctx, peerPubKey)
|
||||||
defer unlockPeer()
|
defer unlockPeer()
|
||||||
|
|
||||||
_, _, _, err = am.SyncPeer(ctx, PeerSync{WireGuardPubKey: peerPubKey, Meta: meta, UpdateAccountPeers: true}, accountID)
|
_, _, _, err = am.SyncPeer(ctx, account.PeerSync{WireGuardPubKey: peerPubKey, Meta: meta, UpdateAccountPeers: true}, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return mapError(ctx, err)
|
return mapError(ctx, err)
|
||||||
}
|
}
|
||||||
@@ -1680,3 +1600,7 @@ func separateGroups(autoGroups []string, allGroups []*types.Group) ([]string, ma
|
|||||||
|
|
||||||
return newAutoGroups, jwtAutoGroups
|
return newAutoGroups, jwtAutoGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (am *DefaultAccountManager) GetStore() store.Store {
|
||||||
|
return am.Store
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package account
|
|
||||||
|
|
||||||
type ExtraSettings struct {
|
|
||||||
// PeerApprovalEnabled enables or disables the need for peers bo be approved by an administrator
|
|
||||||
PeerApprovalEnabled bool
|
|
||||||
|
|
||||||
// IntegratedValidatorGroups list of group IDs to be used with integrated approval configurations
|
|
||||||
IntegratedValidatorGroups []string `gorm:"serializer:json"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy copies the ExtraSettings struct
|
|
||||||
func (e *ExtraSettings) Copy() *ExtraSettings {
|
|
||||||
var cpGroup []string
|
|
||||||
|
|
||||||
return &ExtraSettings{
|
|
||||||
PeerApprovalEnabled: e.PeerApprovalEnabled,
|
|
||||||
IntegratedValidatorGroups: append(cpGroup, e.IntegratedValidatorGroups...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
146
management/server/account/account_manager_interface.go
Normal file
146
management/server/account/account_manager_interface.go
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
package account
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/eko/gocache/v3/cache"
|
||||||
|
|
||||||
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
"github.com/netbirdio/netbird/management/domain"
|
||||||
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
|
"github.com/netbirdio/netbird/management/server/idp"
|
||||||
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
"github.com/netbirdio/netbird/route"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExternalCacheManager cache.CacheInterface[*idp.UserData]
|
||||||
|
|
||||||
|
// nolint
|
||||||
|
type AccountManager interface {
|
||||||
|
GetOrCreateAccountByUser(ctx context.Context, userId, domain string) (*types.Account, error)
|
||||||
|
GetAccount(ctx context.Context, accountID string) (*types.Account, error)
|
||||||
|
CreateSetupKey(ctx context.Context, accountID string, keyName string, keyType types.SetupKeyType, expiresIn time.Duration,
|
||||||
|
autoGroups []string, usageLimit int, userID string, ephemeral bool, allowExtraDNSLabels bool) (*types.SetupKey, error)
|
||||||
|
SaveSetupKey(ctx context.Context, accountID string, key *types.SetupKey, userID string) (*types.SetupKey, error)
|
||||||
|
CreateUser(ctx context.Context, accountID, initiatorUserID string, key *types.UserInfo) (*types.UserInfo, error)
|
||||||
|
DeleteUser(ctx context.Context, accountID, initiatorUserID string, targetUserID string) error
|
||||||
|
DeleteRegularUsers(ctx context.Context, accountID, initiatorUserID string, targetUserIDs []string, userInfos map[string]*types.UserInfo) error
|
||||||
|
InviteUser(ctx context.Context, accountID string, initiatorUserID string, targetUserID string) error
|
||||||
|
ListSetupKeys(ctx context.Context, accountID, userID string) ([]*types.SetupKey, error)
|
||||||
|
SaveUser(ctx context.Context, accountID, initiatorUserID string, update *types.User) (*types.UserInfo, error)
|
||||||
|
SaveOrAddUser(ctx context.Context, accountID, initiatorUserID string, update *types.User, addIfNotExists bool) (*types.UserInfo, error)
|
||||||
|
SaveOrAddUsers(ctx context.Context, accountID, initiatorUserID string, updates []*types.User, addIfNotExists bool) ([]*types.UserInfo, error)
|
||||||
|
GetSetupKey(ctx context.Context, accountID, userID, keyID string) (*types.SetupKey, error)
|
||||||
|
GetAccountByID(ctx context.Context, accountID string, userID string) (*types.Account, error)
|
||||||
|
AccountExists(ctx context.Context, accountID string) (bool, error)
|
||||||
|
GetAccountIDByUserID(ctx context.Context, userID, domain string) (string, error)
|
||||||
|
GetAccountIDFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (string, string, error)
|
||||||
|
DeleteAccount(ctx context.Context, accountID, userID string) error
|
||||||
|
GetUserByID(ctx context.Context, id string) (*types.User, error)
|
||||||
|
GetUserFromUserAuth(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
||||||
|
ListUsers(ctx context.Context, accountID string) ([]*types.User, error)
|
||||||
|
GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error)
|
||||||
|
MarkPeerConnected(ctx context.Context, peerKey string, connected bool, realIP net.IP, accountID string) error
|
||||||
|
DeletePeer(ctx context.Context, accountID, peerID, userID string) error
|
||||||
|
UpdatePeer(ctx context.Context, accountID, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, error)
|
||||||
|
GetNetworkMap(ctx context.Context, peerID string) (*types.NetworkMap, error)
|
||||||
|
GetPeerNetwork(ctx context.Context, peerID string) (*types.Network, error)
|
||||||
|
AddPeer(ctx context.Context, setupKey, userID string, peer *nbpeer.Peer) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
||||||
|
CreatePAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenName string, expiresIn int) (*types.PersonalAccessTokenGenerated, error)
|
||||||
|
DeletePAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenID string) error
|
||||||
|
GetPAT(ctx context.Context, accountID string, initiatorUserID string, targetUserID string, tokenID string) (*types.PersonalAccessToken, error)
|
||||||
|
GetAllPATs(ctx context.Context, accountID string, initiatorUserID string, targetUserID string) ([]*types.PersonalAccessToken, error)
|
||||||
|
GetUsersFromAccount(ctx context.Context, accountID, userID string) (map[string]*types.UserInfo, error)
|
||||||
|
GetGroup(ctx context.Context, accountId, groupID, userID string) (*types.Group, error)
|
||||||
|
GetAllGroups(ctx context.Context, accountID, userID string) ([]*types.Group, error)
|
||||||
|
GetGroupByName(ctx context.Context, groupName, accountID string) (*types.Group, error)
|
||||||
|
SaveGroup(ctx context.Context, accountID, userID string, group *types.Group) error
|
||||||
|
SaveGroups(ctx context.Context, accountID, userID string, newGroups []*types.Group) error
|
||||||
|
DeleteGroup(ctx context.Context, accountId, userId, groupID string) error
|
||||||
|
DeleteGroups(ctx context.Context, accountId, userId string, groupIDs []string) error
|
||||||
|
GroupAddPeer(ctx context.Context, accountId, groupID, peerID string) error
|
||||||
|
GroupDeletePeer(ctx context.Context, accountId, groupID, peerID string) error
|
||||||
|
GetPeerGroups(ctx context.Context, accountID, peerID string) ([]*types.Group, error)
|
||||||
|
GetPolicy(ctx context.Context, accountID, policyID, userID string) (*types.Policy, error)
|
||||||
|
SavePolicy(ctx context.Context, accountID, userID string, policy *types.Policy) (*types.Policy, error)
|
||||||
|
DeletePolicy(ctx context.Context, accountID, policyID, userID string) error
|
||||||
|
ListPolicies(ctx context.Context, accountID, userID string) ([]*types.Policy, error)
|
||||||
|
GetRoute(ctx context.Context, accountID string, routeID route.ID, userID string) (*route.Route, error)
|
||||||
|
CreateRoute(ctx context.Context, accountID string, prefix netip.Prefix, networkType route.NetworkType, domains domain.List, peerID string, peerGroupIDs []string, description string, netID route.NetID, masquerade bool, metric int, groups, accessControlGroupIDs []string, enabled bool, userID string, keepRoute bool) (*route.Route, error)
|
||||||
|
SaveRoute(ctx context.Context, accountID, userID string, route *route.Route) error
|
||||||
|
DeleteRoute(ctx context.Context, accountID string, routeID route.ID, userID string) error
|
||||||
|
ListRoutes(ctx context.Context, accountID, userID string) ([]*route.Route, error)
|
||||||
|
GetNameServerGroup(ctx context.Context, accountID, userID, nsGroupID string) (*nbdns.NameServerGroup, error)
|
||||||
|
CreateNameServerGroup(ctx context.Context, accountID string, name, description string, nameServerList []nbdns.NameServer, groups []string, primary bool, domains []string, enabled bool, userID string, searchDomainsEnabled bool) (*nbdns.NameServerGroup, error)
|
||||||
|
SaveNameServerGroup(ctx context.Context, accountID, userID string, nsGroupToSave *nbdns.NameServerGroup) error
|
||||||
|
DeleteNameServerGroup(ctx context.Context, accountID, nsGroupID, userID string) error
|
||||||
|
ListNameServerGroups(ctx context.Context, accountID string, userID string) ([]*nbdns.NameServerGroup, error)
|
||||||
|
GetDNSDomain() string
|
||||||
|
StoreEvent(ctx context.Context, initiatorID, targetID, accountID string, activityID activity.ActivityDescriber, meta map[string]any)
|
||||||
|
GetEvents(ctx context.Context, accountID, userID string) ([]*activity.Event, error)
|
||||||
|
GetDNSSettings(ctx context.Context, accountID string, userID string) (*types.DNSSettings, error)
|
||||||
|
SaveDNSSettings(ctx context.Context, accountID string, userID string, dnsSettingsToSave *types.DNSSettings) error
|
||||||
|
GetPeer(ctx context.Context, accountID, peerID, userID string) (*nbpeer.Peer, error)
|
||||||
|
UpdateAccountSettings(ctx context.Context, accountID, userID string, newSettings *types.Settings) (*types.Account, error)
|
||||||
|
LoginPeer(ctx context.Context, login PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) // used by peer gRPC API
|
||||||
|
SyncPeer(ctx context.Context, sync PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) // used by peer gRPC API
|
||||||
|
GetAllConnectedPeers() (map[string]struct{}, error)
|
||||||
|
HasConnectedChannel(peerID string) bool
|
||||||
|
GetExternalCacheManager() ExternalCacheManager
|
||||||
|
GetPostureChecks(ctx context.Context, accountID, postureChecksID, userID string) (*posture.Checks, error)
|
||||||
|
SavePostureChecks(ctx context.Context, accountID, userID string, postureChecks *posture.Checks) (*posture.Checks, error)
|
||||||
|
DeletePostureChecks(ctx context.Context, accountID, postureChecksID, userID string) error
|
||||||
|
ListPostureChecks(ctx context.Context, accountID, userID string) ([]*posture.Checks, error)
|
||||||
|
GetIdpManager() idp.Manager
|
||||||
|
UpdateIntegratedValidatorGroups(ctx context.Context, accountID string, userID string, groups []string) error
|
||||||
|
GroupValidation(ctx context.Context, accountId string, groups []string) (bool, error)
|
||||||
|
GetValidatedPeers(ctx context.Context, accountID string) (map[string]struct{}, error)
|
||||||
|
SyncAndMarkPeer(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
||||||
|
OnPeerDisconnected(ctx context.Context, accountID string, peerPubKey string) error
|
||||||
|
SyncPeerMeta(ctx context.Context, peerPubKey string, meta nbpeer.PeerSystemMeta) error
|
||||||
|
FindExistingPostureCheck(accountID string, checks *posture.ChecksDefinition) (*posture.Checks, error)
|
||||||
|
GetAccountIDForPeerKey(ctx context.Context, peerKey string) (string, error)
|
||||||
|
GetAccountSettings(ctx context.Context, accountID string, userID string) (*types.Settings, error)
|
||||||
|
DeleteSetupKey(ctx context.Context, accountID, userID, keyID string) error
|
||||||
|
UpdateAccountPeers(ctx context.Context, accountID string)
|
||||||
|
BuildUserInfosForAccount(ctx context.Context, accountID, initiatorUserID string, accountUsers []*types.User) (map[string]*types.UserInfo, error)
|
||||||
|
SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error
|
||||||
|
GetStore() store.Store
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerSync used as a data object between the gRPC API and AccountManager on Sync request.
|
||||||
|
type PeerSync struct {
|
||||||
|
// WireGuardPubKey is a peers WireGuard public key
|
||||||
|
WireGuardPubKey string
|
||||||
|
// Meta is the system information passed by peer, must be always present
|
||||||
|
Meta nbpeer.PeerSystemMeta
|
||||||
|
// UpdateAccountPeers indicate updating account peers,
|
||||||
|
// which occurs when the peer's metadata is updated
|
||||||
|
UpdateAccountPeers bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// PeerLogin used as a data object between the gRPC API and AccountManager on Login request.
|
||||||
|
type PeerLogin struct {
|
||||||
|
// WireGuardPubKey is a peers WireGuard public key
|
||||||
|
WireGuardPubKey string
|
||||||
|
// SSHKey is a peer's ssh key. Can be empty (e.g., old version do not provide it, or this feature is disabled)
|
||||||
|
SSHKey string
|
||||||
|
// Meta is the system information passed by peer, must be always present.
|
||||||
|
Meta nbpeer.PeerSystemMeta
|
||||||
|
// UserID indicates that JWT was used to log in, and it was valid. Can be empty when SetupKey is used or auth is not required.
|
||||||
|
UserID string
|
||||||
|
// SetupKey references to a server.SetupKey to log in. Can be empty when UserID is used or auth is not required.
|
||||||
|
SetupKey string
|
||||||
|
// ConnectionIP is the real IP of the peer
|
||||||
|
ConnectionIP net.IP
|
||||||
|
|
||||||
|
// ExtraDNSLabels is a list of extra DNS labels that the peer wants to use
|
||||||
|
ExtraDNSLabels []string
|
||||||
|
}
|
||||||
@@ -13,6 +13,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
nbAccount "github.com/netbirdio/netbird/management/server/account"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/util"
|
"github.com/netbirdio/netbird/management/server/util"
|
||||||
|
|
||||||
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||||
@@ -35,7 +38,7 @@ import (
|
|||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
func verifyCanAddPeerToAccount(t *testing.T, manager AccountManager, account *types.Account, userID string) {
|
func verifyCanAddPeerToAccount(t *testing.T, manager nbAccount.AccountManager, account *types.Account, userID string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
peer := &nbpeer.Peer{
|
peer := &nbpeer.Peer{
|
||||||
Key: "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8=",
|
Key: "BhRPtynAAYRDy08+q4HTMsos8fs4plTP4NOSh7C1ry8=",
|
||||||
@@ -1402,7 +1405,7 @@ func TestAccountManager_DeletePeer(t *testing.T) {
|
|||||||
assert.Equal(t, peer.IP.String(), fmt.Sprint(ev.Meta["ip"]))
|
assert.Equal(t, peer.IP.String(), fmt.Sprint(ev.Meta["ip"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getEvent(t *testing.T, accountID string, manager AccountManager, eventType activity.Activity) *activity.Event {
|
func getEvent(t *testing.T, accountID string, manager nbAccount.AccountManager, eventType activity.Activity) *activity.Event {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -2808,7 +2811,7 @@ func createManager(t TB) (*DefaultAccountManager, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics)
|
manager, err := BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.cloud", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -3023,7 +3026,7 @@ func BenchmarkLoginPeer_ExistingPeer(b *testing.B) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, _, _, err := manager.LoginPeer(context.Background(), PeerLogin{
|
_, _, _, err := manager.LoginPeer(context.Background(), nbAccount.PeerLogin{
|
||||||
WireGuardPubKey: account.Peers["peer-1"].Key,
|
WireGuardPubKey: account.Peers["peer-1"].Key,
|
||||||
SSHKey: "someKey",
|
SSHKey: "someKey",
|
||||||
Meta: nbpeer.PeerSystemMeta{Hostname: strconv.Itoa(i)},
|
Meta: nbpeer.PeerSystemMeta{Hostname: strconv.Itoa(i)},
|
||||||
@@ -3098,7 +3101,7 @@ func BenchmarkLoginPeer_NewPeer(b *testing.B) {
|
|||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, _, _, err := manager.LoginPeer(context.Background(), PeerLogin{
|
_, _, _, err := manager.LoginPeer(context.Background(), nbAccount.PeerLogin{
|
||||||
WireGuardPubKey: "some-new-key" + strconv.Itoa(i),
|
WireGuardPubKey: "some-new-key" + strconv.Itoa(i),
|
||||||
SSHKey: "someKey",
|
SSHKey: "someKey",
|
||||||
Meta: nbpeer.PeerSystemMeta{Hostname: strconv.Itoa(i)},
|
Meta: nbpeer.PeerSystemMeta{Hostname: strconv.Itoa(i)},
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
@@ -208,7 +210,7 @@ func createDNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics)
|
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.test", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDNSStore(t *testing.T) (store.Store, error) {
|
func createDNSStore(t *testing.T) (store.Store, error) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
nbAccount "github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
@@ -34,7 +35,7 @@ type ephemeralPeer struct {
|
|||||||
// automatically. Inactivity means the peer disconnected from the Management server.
|
// automatically. Inactivity means the peer disconnected from the Management server.
|
||||||
type EphemeralManager struct {
|
type EphemeralManager struct {
|
||||||
store store.Store
|
store store.Store
|
||||||
accountManager AccountManager
|
accountManager nbAccount.AccountManager
|
||||||
|
|
||||||
headPeer *ephemeralPeer
|
headPeer *ephemeralPeer
|
||||||
tailPeer *ephemeralPeer
|
tailPeer *ephemeralPeer
|
||||||
@@ -43,7 +44,7 @@ type EphemeralManager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewEphemeralManager instantiate new EphemeralManager
|
// NewEphemeralManager instantiate new EphemeralManager
|
||||||
func NewEphemeralManager(store store.Store, accountManager AccountManager) *EphemeralManager {
|
func NewEphemeralManager(store store.Store, accountManager nbAccount.AccountManager) *EphemeralManager {
|
||||||
return &EphemeralManager{
|
return &EphemeralManager{
|
||||||
store: store,
|
store: store,
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
nbAccount "github.com/netbirdio/netbird/management/server/account"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
@@ -27,7 +28,7 @@ func (s *MockStore) GetAllEphemeralPeers(_ context.Context, _ store.LockingStren
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MocAccountManager struct {
|
type MocAccountManager struct {
|
||||||
AccountManager
|
nbAccount.AccountManager
|
||||||
store *MockStore
|
store *MockStore
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +37,10 @@ func (a MocAccountManager) DeletePeer(_ context.Context, accountID, peerID, user
|
|||||||
return nil //nolint:nil
|
return nil //nolint:nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a MocAccountManager) GetStore() store.Store {
|
||||||
|
return a.store
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewManager(t *testing.T) {
|
func TestNewManager(t *testing.T) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
timeNow = func() time.Time {
|
timeNow = func() time.Time {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/permissions"
|
"github.com/netbirdio/netbird/management/server/permissions"
|
||||||
@@ -24,13 +24,13 @@ type Manager interface {
|
|||||||
type managerImpl struct {
|
type managerImpl struct {
|
||||||
store store.Store
|
store store.Store
|
||||||
permissionsManager permissions.Manager
|
permissionsManager permissions.Manager
|
||||||
accountManager s.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockManager struct {
|
type mockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager s.AccountManager) Manager {
|
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager account.AccountManager) Manager {
|
||||||
return &managerImpl{
|
return &managerImpl{
|
||||||
store: store,
|
store: store,
|
||||||
permissionsManager: permissionsManager,
|
permissionsManager: permissionsManager,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
pb "github.com/golang/protobuf/proto" // nolint
|
pb "github.com/golang/protobuf/proto" // nolint
|
||||||
"github.com/golang/protobuf/ptypes/timestamp"
|
"github.com/golang/protobuf/ptypes/timestamp"
|
||||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
||||||
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
@@ -20,6 +21,8 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/netbird/encryption"
|
"github.com/netbirdio/netbird/encryption"
|
||||||
"github.com/netbirdio/netbird/management/proto"
|
"github.com/netbirdio/netbird/management/proto"
|
||||||
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/auth"
|
"github.com/netbirdio/netbird/management/server/auth"
|
||||||
nbContext "github.com/netbirdio/netbird/management/server/context"
|
nbContext "github.com/netbirdio/netbird/management/server/context"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
@@ -32,7 +35,7 @@ import (
|
|||||||
|
|
||||||
// GRPCServer an instance of a Management gRPC API server
|
// GRPCServer an instance of a Management gRPC API server
|
||||||
type GRPCServer struct {
|
type GRPCServer struct {
|
||||||
accountManager AccountManager
|
accountManager account.AccountManager
|
||||||
settingsManager settings.Manager
|
settingsManager settings.Manager
|
||||||
wgKey wgtypes.Key
|
wgKey wgtypes.Key
|
||||||
proto.UnimplementedManagementServiceServer
|
proto.UnimplementedManagementServiceServer
|
||||||
@@ -49,7 +52,7 @@ type GRPCServer struct {
|
|||||||
func NewServer(
|
func NewServer(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
config *Config,
|
config *Config,
|
||||||
accountManager AccountManager,
|
accountManager account.AccountManager,
|
||||||
settingsManager settings.Manager,
|
settingsManager settings.Manager,
|
||||||
peersUpdateManager *PeersUpdateManager,
|
peersUpdateManager *PeersUpdateManager,
|
||||||
secretsManager SecretsManager,
|
secretsManager SecretsManager,
|
||||||
@@ -457,7 +460,7 @@ func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*p
|
|||||||
sshKey = loginReq.GetPeerKeys().GetSshPubKey()
|
sshKey = loginReq.GetPeerKeys().GetSshPubKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
peer, netMap, postureChecks, err := s.accountManager.LoginPeer(ctx, PeerLogin{
|
peer, netMap, postureChecks, err := s.accountManager.LoginPeer(ctx, account.PeerLogin{
|
||||||
WireGuardPubKey: peerKey.String(),
|
WireGuardPubKey: peerKey.String(),
|
||||||
SSHKey: string(sshKey),
|
SSHKey: string(sshKey),
|
||||||
Meta: extractPeerMeta(ctx, loginReq.GetMeta()),
|
Meta: extractPeerMeta(ctx, loginReq.GetMeta()),
|
||||||
@@ -486,7 +489,7 @@ func (s *GRPCServer) Login(ctx context.Context, req *proto.EncryptedMessage) (*p
|
|||||||
|
|
||||||
// if peer has reached this point then it has logged in
|
// if peer has reached this point then it has logged in
|
||||||
loginResp := &proto.LoginResponse{
|
loginResp := &proto.LoginResponse{
|
||||||
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken),
|
NetbirdConfig: toNetbirdConfig(s.config, nil, relayToken, nil),
|
||||||
PeerConfig: toPeerConfig(peer, netMap.Network, s.accountManager.GetDNSDomain(), false),
|
PeerConfig: toPeerConfig(peer, netMap.Network, s.accountManager.GetDNSDomain(), false),
|
||||||
Checks: toProtocolChecks(ctx, postureChecks),
|
Checks: toProtocolChecks(ctx, postureChecks),
|
||||||
}
|
}
|
||||||
@@ -544,7 +547,7 @@ func ToResponseProto(configProto Protocol) proto.HostConfig_Protocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toNetbirdConfig(config *Config, turnCredentials *Token, relayToken *Token) *proto.NetbirdConfig {
|
func toNetbirdConfig(config *Config, turnCredentials *Token, relayToken *Token, extraSettings *types.ExtraSettings) *proto.NetbirdConfig {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -592,7 +595,7 @@ func toNetbirdConfig(config *Config, turnCredentials *Token, relayToken *Token)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &proto.NetbirdConfig{
|
nbConfig := &proto.NetbirdConfig{
|
||||||
Stuns: stuns,
|
Stuns: stuns,
|
||||||
Turns: turns,
|
Turns: turns,
|
||||||
Signal: &proto.HostConfig{
|
Signal: &proto.HostConfig{
|
||||||
@@ -601,6 +604,10 @@ func toNetbirdConfig(config *Config, turnCredentials *Token, relayToken *Token)
|
|||||||
},
|
},
|
||||||
Relay: relayCfg,
|
Relay: relayCfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
integrations.ExtendNetBirdConfig(nbConfig, extraSettings)
|
||||||
|
|
||||||
|
return nbConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func toPeerConfig(peer *nbpeer.Peer, network *types.Network, dnsName string, dnsResolutionOnRoutingPeerEnabled bool) *proto.PeerConfig {
|
func toPeerConfig(peer *nbpeer.Peer, network *types.Network, dnsName string, dnsResolutionOnRoutingPeerEnabled bool) *proto.PeerConfig {
|
||||||
@@ -614,10 +621,10 @@ func toPeerConfig(peer *nbpeer.Peer, network *types.Network, dnsName string, dns
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSyncResponse(ctx context.Context, config *Config, peer *nbpeer.Peer, turnCredentials *Token, relayCredentials *Token, networkMap *types.NetworkMap, dnsName string, checks []*posture.Checks, dnsCache *DNSConfigCache, dnsResolutionOnRoutingPeerEnbled bool) *proto.SyncResponse {
|
func toSyncResponse(ctx context.Context, config *Config, peer *nbpeer.Peer, turnCredentials *Token, relayCredentials *Token, networkMap *types.NetworkMap, dnsName string, checks []*posture.Checks, dnsCache *DNSConfigCache, dnsResolutionOnRoutingPeerEnabled bool, extraSettings *types.ExtraSettings) *proto.SyncResponse {
|
||||||
response := &proto.SyncResponse{
|
response := &proto.SyncResponse{
|
||||||
NetbirdConfig: toNetbirdConfig(config, turnCredentials, relayCredentials),
|
NetbirdConfig: toNetbirdConfig(config, turnCredentials, relayCredentials, extraSettings),
|
||||||
PeerConfig: toPeerConfig(peer, networkMap.Network, dnsName, dnsResolutionOnRoutingPeerEnbled),
|
PeerConfig: toPeerConfig(peer, networkMap.Network, dnsName, dnsResolutionOnRoutingPeerEnabled),
|
||||||
NetworkMap: &proto.NetworkMap{
|
NetworkMap: &proto.NetworkMap{
|
||||||
Serial: networkMap.Network.CurrentSerial(),
|
Serial: networkMap.Network.CurrentSerial(),
|
||||||
Routes: toProtocolRoutes(networkMap.Routes),
|
Routes: toProtocolRoutes(networkMap.Routes),
|
||||||
@@ -645,6 +652,14 @@ func toSyncResponse(ctx context.Context, config *Config, peer *nbpeer.Peer, turn
|
|||||||
response.NetworkMap.RoutesFirewallRules = routesFirewallRules
|
response.NetworkMap.RoutesFirewallRules = routesFirewallRules
|
||||||
response.NetworkMap.RoutesFirewallRulesIsEmpty = len(routesFirewallRules) == 0
|
response.NetworkMap.RoutesFirewallRulesIsEmpty = len(routesFirewallRules) == 0
|
||||||
|
|
||||||
|
if networkMap.ForwardingRules != nil {
|
||||||
|
forwardingRules := make([]*proto.ForwardingRule, 0, len(networkMap.ForwardingRules))
|
||||||
|
for _, rule := range networkMap.ForwardingRules {
|
||||||
|
forwardingRules = append(forwardingRules, rule.ToProto())
|
||||||
|
}
|
||||||
|
response.NetworkMap.ForwardingRules = forwardingRules
|
||||||
|
}
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,12 +700,12 @@ func (s *GRPCServer) sendInitialSync(ctx context.Context, peerKey wgtypes.Key, p
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
settings, err := s.settingsManager.GetSettings(ctx, peer.AccountID, peer.UserID)
|
settings, err := s.settingsManager.GetSettings(ctx, peer.AccountID, activity.SystemInitiator)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return status.Errorf(codes.Internal, "error handling request")
|
return status.Errorf(codes.Internal, "error handling request")
|
||||||
}
|
}
|
||||||
|
|
||||||
plainResp := toSyncResponse(ctx, s.config, peer, turnToken, relayToken, networkMap, s.accountManager.GetDNSDomain(), postureChecks, nil, settings.RoutingPeerDNSResolutionEnabled)
|
plainResp := toSyncResponse(ctx, s.config, peer, turnToken, relayToken, networkMap, s.accountManager.GetDNSDomain(), postureChecks, nil, settings.RoutingPeerDNSResolutionEnabled, settings.Extra)
|
||||||
|
|
||||||
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, plainResp)
|
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, plainResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ tags:
|
|||||||
description: View information about the account and network events.
|
description: View information about the account and network events.
|
||||||
- name: Accounts
|
- name: Accounts
|
||||||
description: View information about the accounts.
|
description: View information about the accounts.
|
||||||
|
- name: Ingress Ports
|
||||||
|
description: Interact with and view information about the ingress peers and ports.
|
||||||
|
x-cloud-only: true
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Account:
|
Account:
|
||||||
@@ -103,6 +106,10 @@ components:
|
|||||||
description: (Cloud only) Enables or disables peer approval globally. If enabled, all peers added will be in pending state until approved by an admin.
|
description: (Cloud only) Enables or disables peer approval globally. If enabled, all peers added will be in pending state until approved by an admin.
|
||||||
type: boolean
|
type: boolean
|
||||||
example: true
|
example: true
|
||||||
|
network_traffic_logs_enabled:
|
||||||
|
description: Enables or disables network traffic logs. If enabled, all network traffic logs from peers will be stored.
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
AccountRequest:
|
AccountRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1597,6 +1604,223 @@ components:
|
|||||||
- initiator_email
|
- initiator_email
|
||||||
- target_id
|
- target_id
|
||||||
- meta
|
- meta
|
||||||
|
IngressPeerCreateRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
peer_id:
|
||||||
|
description: ID of the peer that is used as an ingress peer
|
||||||
|
type: string
|
||||||
|
example: ch8i4ug6lnn4g9hqv7m0
|
||||||
|
enabled:
|
||||||
|
description: Defines if an ingress peer is enabled
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
fallback:
|
||||||
|
description: Defines if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
required:
|
||||||
|
- peer_id
|
||||||
|
- enabled
|
||||||
|
- fallback
|
||||||
|
IngressPeerUpdateRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
enabled:
|
||||||
|
description: Defines if an ingress peer is enabled
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
fallback:
|
||||||
|
description: Defines if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
required:
|
||||||
|
- enabled
|
||||||
|
- fallback
|
||||||
|
IngressPeer:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: ID of the ingress peer
|
||||||
|
type: string
|
||||||
|
example: ch8i4ug6lnn4g9hqv7m0
|
||||||
|
peer_id:
|
||||||
|
description: ID of the peer that is used as an ingress peer
|
||||||
|
type: string
|
||||||
|
example: x7p3kqf2rdd8j5zxw4n9
|
||||||
|
ingress_ip:
|
||||||
|
description: Ingress IP address of the ingress peer where the traffic arrives
|
||||||
|
type: string
|
||||||
|
example: 192.34.0.123
|
||||||
|
available_ports:
|
||||||
|
$ref: '#/components/schemas/AvailablePorts'
|
||||||
|
enabled:
|
||||||
|
description: Indicates if an ingress peer is enabled
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
connected:
|
||||||
|
description: Indicates if an ingress peer is connected to the management server
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
fallback:
|
||||||
|
description: Indicates if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
region:
|
||||||
|
description: Region of the ingress peer
|
||||||
|
type: string
|
||||||
|
example: germany
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- peer_id
|
||||||
|
- ingress_ip
|
||||||
|
- available_ports
|
||||||
|
- enabled
|
||||||
|
- connected
|
||||||
|
- fallback
|
||||||
|
- region
|
||||||
|
|
||||||
|
AvailablePorts:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
tcp:
|
||||||
|
description: Number of available TCP ports left on the ingress peer
|
||||||
|
type: integer
|
||||||
|
example: 45765
|
||||||
|
udp:
|
||||||
|
description: Number of available UDP ports left on the ingress peer
|
||||||
|
type: integer
|
||||||
|
example: 50000
|
||||||
|
required:
|
||||||
|
- tcp
|
||||||
|
- udp
|
||||||
|
IngressPortAllocationRequest:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
description: Name of the ingress port allocation
|
||||||
|
type: string
|
||||||
|
example: Ingress Port Allocation 1
|
||||||
|
enabled:
|
||||||
|
description: Indicates if an ingress port allocation is enabled
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
port_ranges:
|
||||||
|
description: List of port ranges that are forwarded by the ingress peer
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocationRequestPortRange'
|
||||||
|
direct_port:
|
||||||
|
description: Direct port allocation
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocationRequestDirectPort'
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- enabled
|
||||||
|
IngressPortAllocationRequestPortRange:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
start:
|
||||||
|
description: The starting port of the range of forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 80
|
||||||
|
end:
|
||||||
|
description: The ending port of the range of forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 320
|
||||||
|
protocol:
|
||||||
|
description: The protocol accepted by the port range
|
||||||
|
type: string
|
||||||
|
enum: [ "tcp", "udp", "tcp/udp" ]
|
||||||
|
example: tcp
|
||||||
|
required:
|
||||||
|
- start
|
||||||
|
- end
|
||||||
|
- protocol
|
||||||
|
IngressPortAllocationRequestDirectPort:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
count:
|
||||||
|
description: The number of ports to be forwarded
|
||||||
|
type: integer
|
||||||
|
example: 5
|
||||||
|
protocol:
|
||||||
|
description: The protocol accepted by the port
|
||||||
|
type: string
|
||||||
|
enum: [ "tcp", "udp", "tcp/udp" ]
|
||||||
|
example: udp
|
||||||
|
required:
|
||||||
|
- count
|
||||||
|
- protocol
|
||||||
|
IngressPortAllocation:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
description: ID of the ingress port allocation
|
||||||
|
type: string
|
||||||
|
example: ch8i4ug6lnn4g9hqv7m0
|
||||||
|
name:
|
||||||
|
description: Name of the ingress port allocation
|
||||||
|
type: string
|
||||||
|
example: Ingress Peer Allocation 1
|
||||||
|
ingress_peer_id:
|
||||||
|
description: ID of the ingress peer that forwards the ports
|
||||||
|
type: string
|
||||||
|
example: x7p3kqf2rdd8j5zxw4n9
|
||||||
|
region:
|
||||||
|
description: Region of the ingress peer
|
||||||
|
type: string
|
||||||
|
example: germany
|
||||||
|
enabled:
|
||||||
|
description: Indicates if an ingress port allocation is enabled
|
||||||
|
type: boolean
|
||||||
|
example: true
|
||||||
|
ingress_ip:
|
||||||
|
description: Ingress IP address of the ingress peer where the traffic arrives
|
||||||
|
type: string
|
||||||
|
example:
|
||||||
|
port_range_mappings:
|
||||||
|
description: List of port ranges that are allowed to be used by the ingress peer
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocationPortMapping'
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- name
|
||||||
|
- ingress_peer_id
|
||||||
|
- region
|
||||||
|
- enabled
|
||||||
|
- ingress_ip
|
||||||
|
- port_range_mappings
|
||||||
|
IngressPortAllocationPortMapping:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
translated_start:
|
||||||
|
description: The starting port of the translated range of forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 80
|
||||||
|
translated_end:
|
||||||
|
description: The ending port of the translated range of forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 320
|
||||||
|
ingress_start:
|
||||||
|
description: The starting port of the range of ingress ports mapped to the forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 1080
|
||||||
|
ingress_end:
|
||||||
|
description: The ending port of the range of ingress ports mapped to the forwarded ports
|
||||||
|
type: integer
|
||||||
|
example: 1320
|
||||||
|
protocol:
|
||||||
|
description: Protocol accepted by the ports
|
||||||
|
type: string
|
||||||
|
enum: [ "tcp", "udp", "tcp/udp" ]
|
||||||
|
example: tcp
|
||||||
|
required:
|
||||||
|
- translated_start
|
||||||
|
- translated_end
|
||||||
|
- ingress_start
|
||||||
|
- ingress_end
|
||||||
|
- protocol
|
||||||
responses:
|
responses:
|
||||||
not_found:
|
not_found:
|
||||||
description: Resource not found
|
description: Resource not found
|
||||||
@@ -2009,6 +2233,17 @@ paths:
|
|||||||
summary: List all Peers
|
summary: List all Peers
|
||||||
description: Returns a list of all peers
|
description: Returns a list of all peers
|
||||||
tags: [ Peers ]
|
tags: [ Peers ]
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: name
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Filter peers by name
|
||||||
|
- in: query
|
||||||
|
name: ip
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Filter peers by IP address
|
||||||
security:
|
security:
|
||||||
- BearerAuth: [ ]
|
- BearerAuth: [ ]
|
||||||
- TokenAuth: [ ]
|
- TokenAuth: [ ]
|
||||||
@@ -2152,6 +2387,335 @@ paths:
|
|||||||
"$ref": "#/components/responses/forbidden"
|
"$ref": "#/components/responses/forbidden"
|
||||||
'500':
|
'500':
|
||||||
"$ref": "#/components/responses/internal_error"
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
/api/peers/{peerId}/ingress/ports:
|
||||||
|
get:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: List all Ingress Port Allocations for a Peer
|
||||||
|
description: Returns a list of all ingress port allocations for a peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: peerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of a peer
|
||||||
|
- in: query
|
||||||
|
name: name
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: Filters ingress port allocations by name
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A JSON Array of Ingress Port Allocations
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocation'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
post:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Create a Ingress Port Allocation
|
||||||
|
description: Creates a new ingress port allocation for a peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: peerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of a peer
|
||||||
|
requestBody:
|
||||||
|
description: New Ingress Port Allocation request
|
||||||
|
content:
|
||||||
|
'application/json':
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocationRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Port Allocation object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocation'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
/api/peers/{peerId}/ingress/ports/{allocationId}:
|
||||||
|
get:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Retrieve a Ingress Port Allocation
|
||||||
|
description: Get information about an ingress port allocation
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: peerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of a peer
|
||||||
|
- in: path
|
||||||
|
name: allocationId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress port allocation
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Port Allocation object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocation'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
put:
|
||||||
|
x-cloud-only: true
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: peerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of a peer
|
||||||
|
- in: path
|
||||||
|
name: allocationId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress port allocation
|
||||||
|
requestBody:
|
||||||
|
description: update an ingress port allocation
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocationRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Port Allocation object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPortAllocation'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
delete:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Delete a Ingress Port Allocation
|
||||||
|
description: Delete an ingress port allocation
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: peerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of a peer
|
||||||
|
- in: path
|
||||||
|
name: allocationId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress port allocation
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Delete status code
|
||||||
|
content: { }
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
/api/ingress/peers:
|
||||||
|
get:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: List all Ingress Peers
|
||||||
|
description: Returns a list of all ingress peers
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A JSON Array of Ingress Peers
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/IngressPeer'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
post:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Create a Ingress Peer
|
||||||
|
description: Creates a new ingress peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
requestBody:
|
||||||
|
description: New Ingress Peer request
|
||||||
|
content:
|
||||||
|
'application/json':
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPeerCreateRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Peer object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPeer'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
/api/ingress/peers/{ingressPeerId}:
|
||||||
|
get:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Retrieve a Ingress Peer
|
||||||
|
description: Get information about an ingress peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: ingressPeerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress peer
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Peer object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPeer'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
put:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Update a Ingress Peer
|
||||||
|
description: Update information about an ingress peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: ingressPeerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress peer
|
||||||
|
requestBody:
|
||||||
|
description: update an ingress peer
|
||||||
|
content:
|
||||||
|
'application/json':
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPeerUpdateRequest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: A Ingress Peer object
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/IngressPeer'
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
|
delete:
|
||||||
|
x-cloud-only: true
|
||||||
|
summary: Delete a Ingress Peer
|
||||||
|
description: Delete an ingress peer
|
||||||
|
tags: [ Ingress Ports ]
|
||||||
|
security:
|
||||||
|
- BearerAuth: [ ]
|
||||||
|
- TokenAuth: [ ]
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: ingressPeerId
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
description: The unique identifier of an ingress peer
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Delete status code
|
||||||
|
content: { }
|
||||||
|
'400':
|
||||||
|
"$ref": "#/components/responses/bad_request"
|
||||||
|
'401':
|
||||||
|
"$ref": "#/components/responses/requires_authentication"
|
||||||
|
'403':
|
||||||
|
"$ref": "#/components/responses/forbidden"
|
||||||
|
'500':
|
||||||
|
"$ref": "#/components/responses/internal_error"
|
||||||
/api/setup-keys:
|
/api/setup-keys:
|
||||||
get:
|
get:
|
||||||
summary: List all Setup Keys
|
summary: List all Setup Keys
|
||||||
|
|||||||
@@ -83,6 +83,27 @@ const (
|
|||||||
GroupMinimumIssuedJwt GroupMinimumIssued = "jwt"
|
GroupMinimumIssuedJwt GroupMinimumIssued = "jwt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defines values for IngressPortAllocationPortMappingProtocol.
|
||||||
|
const (
|
||||||
|
IngressPortAllocationPortMappingProtocolTcp IngressPortAllocationPortMappingProtocol = "tcp"
|
||||||
|
IngressPortAllocationPortMappingProtocolTcpudp IngressPortAllocationPortMappingProtocol = "tcp/udp"
|
||||||
|
IngressPortAllocationPortMappingProtocolUdp IngressPortAllocationPortMappingProtocol = "udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Defines values for IngressPortAllocationRequestDirectPortProtocol.
|
||||||
|
const (
|
||||||
|
IngressPortAllocationRequestDirectPortProtocolTcp IngressPortAllocationRequestDirectPortProtocol = "tcp"
|
||||||
|
IngressPortAllocationRequestDirectPortProtocolTcpudp IngressPortAllocationRequestDirectPortProtocol = "tcp/udp"
|
||||||
|
IngressPortAllocationRequestDirectPortProtocolUdp IngressPortAllocationRequestDirectPortProtocol = "udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Defines values for IngressPortAllocationRequestPortRangeProtocol.
|
||||||
|
const (
|
||||||
|
IngressPortAllocationRequestPortRangeProtocolTcp IngressPortAllocationRequestPortRangeProtocol = "tcp"
|
||||||
|
IngressPortAllocationRequestPortRangeProtocolTcpudp IngressPortAllocationRequestPortRangeProtocol = "tcp/udp"
|
||||||
|
IngressPortAllocationRequestPortRangeProtocolUdp IngressPortAllocationRequestPortRangeProtocol = "udp"
|
||||||
|
)
|
||||||
|
|
||||||
// Defines values for NameserverNsType.
|
// Defines values for NameserverNsType.
|
||||||
const (
|
const (
|
||||||
NameserverNsTypeUdp NameserverNsType = "udp"
|
NameserverNsTypeUdp NameserverNsType = "udp"
|
||||||
@@ -209,6 +230,9 @@ type Account struct {
|
|||||||
|
|
||||||
// AccountExtraSettings defines model for AccountExtraSettings.
|
// AccountExtraSettings defines model for AccountExtraSettings.
|
||||||
type AccountExtraSettings struct {
|
type AccountExtraSettings struct {
|
||||||
|
// NetworkTrafficLogsEnabled Enables or disables network traffic logs. If enabled, all network traffic logs from peers will be stored.
|
||||||
|
NetworkTrafficLogsEnabled *bool `json:"network_traffic_logs_enabled,omitempty"`
|
||||||
|
|
||||||
// PeerApprovalEnabled (Cloud only) Enables or disables peer approval globally. If enabled, all peers added will be in pending state until approved by an admin.
|
// PeerApprovalEnabled (Cloud only) Enables or disables peer approval globally. If enabled, all peers added will be in pending state until approved by an admin.
|
||||||
PeerApprovalEnabled *bool `json:"peer_approval_enabled,omitempty"`
|
PeerApprovalEnabled *bool `json:"peer_approval_enabled,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -253,6 +277,15 @@ type AccountSettings struct {
|
|||||||
RoutingPeerDnsResolutionEnabled *bool `json:"routing_peer_dns_resolution_enabled,omitempty"`
|
RoutingPeerDnsResolutionEnabled *bool `json:"routing_peer_dns_resolution_enabled,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AvailablePorts defines model for AvailablePorts.
|
||||||
|
type AvailablePorts struct {
|
||||||
|
// Tcp Number of available TCP ports left on the ingress peer
|
||||||
|
Tcp int `json:"tcp"`
|
||||||
|
|
||||||
|
// Udp Number of available UDP ports left on the ingress peer
|
||||||
|
Udp int `json:"udp"`
|
||||||
|
}
|
||||||
|
|
||||||
// Checks List of objects that perform the actual checks
|
// Checks List of objects that perform the actual checks
|
||||||
type Checks struct {
|
type Checks struct {
|
||||||
// GeoLocationCheck Posture check for geo location
|
// GeoLocationCheck Posture check for geo location
|
||||||
@@ -426,6 +459,139 @@ type GroupRequest struct {
|
|||||||
Resources *[]Resource `json:"resources,omitempty"`
|
Resources *[]Resource `json:"resources,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IngressPeer defines model for IngressPeer.
|
||||||
|
type IngressPeer struct {
|
||||||
|
AvailablePorts AvailablePorts `json:"available_ports"`
|
||||||
|
|
||||||
|
// Connected Indicates if an ingress peer is connected to the management server
|
||||||
|
Connected bool `json:"connected"`
|
||||||
|
|
||||||
|
// Enabled Indicates if an ingress peer is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Fallback Indicates if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
Fallback bool `json:"fallback"`
|
||||||
|
|
||||||
|
// Id ID of the ingress peer
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// IngressIp Ingress IP address of the ingress peer where the traffic arrives
|
||||||
|
IngressIp string `json:"ingress_ip"`
|
||||||
|
|
||||||
|
// PeerId ID of the peer that is used as an ingress peer
|
||||||
|
PeerId string `json:"peer_id"`
|
||||||
|
|
||||||
|
// Region Region of the ingress peer
|
||||||
|
Region string `json:"region"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPeerCreateRequest defines model for IngressPeerCreateRequest.
|
||||||
|
type IngressPeerCreateRequest struct {
|
||||||
|
// Enabled Defines if an ingress peer is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Fallback Defines if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
Fallback bool `json:"fallback"`
|
||||||
|
|
||||||
|
// PeerId ID of the peer that is used as an ingress peer
|
||||||
|
PeerId string `json:"peer_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPeerUpdateRequest defines model for IngressPeerUpdateRequest.
|
||||||
|
type IngressPeerUpdateRequest struct {
|
||||||
|
// Enabled Defines if an ingress peer is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Fallback Defines if an ingress peer can be used as a fallback if no ingress peer can be found in the region of the forwarded peer
|
||||||
|
Fallback bool `json:"fallback"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocation defines model for IngressPortAllocation.
|
||||||
|
type IngressPortAllocation struct {
|
||||||
|
// Enabled Indicates if an ingress port allocation is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Id ID of the ingress port allocation
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// IngressIp Ingress IP address of the ingress peer where the traffic arrives
|
||||||
|
IngressIp string `json:"ingress_ip"`
|
||||||
|
|
||||||
|
// IngressPeerId ID of the ingress peer that forwards the ports
|
||||||
|
IngressPeerId string `json:"ingress_peer_id"`
|
||||||
|
|
||||||
|
// Name Name of the ingress port allocation
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// PortRangeMappings List of port ranges that are allowed to be used by the ingress peer
|
||||||
|
PortRangeMappings []IngressPortAllocationPortMapping `json:"port_range_mappings"`
|
||||||
|
|
||||||
|
// Region Region of the ingress peer
|
||||||
|
Region string `json:"region"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocationPortMapping defines model for IngressPortAllocationPortMapping.
|
||||||
|
type IngressPortAllocationPortMapping struct {
|
||||||
|
// IngressEnd The ending port of the range of ingress ports mapped to the forwarded ports
|
||||||
|
IngressEnd int `json:"ingress_end"`
|
||||||
|
|
||||||
|
// IngressStart The starting port of the range of ingress ports mapped to the forwarded ports
|
||||||
|
IngressStart int `json:"ingress_start"`
|
||||||
|
|
||||||
|
// Protocol Protocol accepted by the ports
|
||||||
|
Protocol IngressPortAllocationPortMappingProtocol `json:"protocol"`
|
||||||
|
|
||||||
|
// TranslatedEnd The ending port of the translated range of forwarded ports
|
||||||
|
TranslatedEnd int `json:"translated_end"`
|
||||||
|
|
||||||
|
// TranslatedStart The starting port of the translated range of forwarded ports
|
||||||
|
TranslatedStart int `json:"translated_start"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocationPortMappingProtocol Protocol accepted by the ports
|
||||||
|
type IngressPortAllocationPortMappingProtocol string
|
||||||
|
|
||||||
|
// IngressPortAllocationRequest defines model for IngressPortAllocationRequest.
|
||||||
|
type IngressPortAllocationRequest struct {
|
||||||
|
DirectPort *IngressPortAllocationRequestDirectPort `json:"direct_port,omitempty"`
|
||||||
|
|
||||||
|
// Enabled Indicates if an ingress port allocation is enabled
|
||||||
|
Enabled bool `json:"enabled"`
|
||||||
|
|
||||||
|
// Name Name of the ingress port allocation
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// PortRanges List of port ranges that are forwarded by the ingress peer
|
||||||
|
PortRanges *[]IngressPortAllocationRequestPortRange `json:"port_ranges,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocationRequestDirectPort defines model for IngressPortAllocationRequestDirectPort.
|
||||||
|
type IngressPortAllocationRequestDirectPort struct {
|
||||||
|
// Count The number of ports to be forwarded
|
||||||
|
Count int `json:"count"`
|
||||||
|
|
||||||
|
// Protocol The protocol accepted by the port
|
||||||
|
Protocol IngressPortAllocationRequestDirectPortProtocol `json:"protocol"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocationRequestDirectPortProtocol The protocol accepted by the port
|
||||||
|
type IngressPortAllocationRequestDirectPortProtocol string
|
||||||
|
|
||||||
|
// IngressPortAllocationRequestPortRange defines model for IngressPortAllocationRequestPortRange.
|
||||||
|
type IngressPortAllocationRequestPortRange struct {
|
||||||
|
// End The ending port of the range of forwarded ports
|
||||||
|
End int `json:"end"`
|
||||||
|
|
||||||
|
// Protocol The protocol accepted by the port range
|
||||||
|
Protocol IngressPortAllocationRequestPortRangeProtocol `json:"protocol"`
|
||||||
|
|
||||||
|
// Start The starting port of the range of forwarded ports
|
||||||
|
Start int `json:"start"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IngressPortAllocationRequestPortRangeProtocol The protocol accepted by the port range
|
||||||
|
type IngressPortAllocationRequestPortRangeProtocol string
|
||||||
|
|
||||||
// Location Describe geographical location information
|
// Location Describe geographical location information
|
||||||
type Location struct {
|
type Location struct {
|
||||||
// CityName Commonly used English name of the city
|
// CityName Commonly used English name of the city
|
||||||
@@ -1466,6 +1632,21 @@ type UserRequest struct {
|
|||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetApiPeersParams defines parameters for GetApiPeers.
|
||||||
|
type GetApiPeersParams struct {
|
||||||
|
// Name Filter peers by name
|
||||||
|
Name *string `form:"name,omitempty" json:"name,omitempty"`
|
||||||
|
|
||||||
|
// Ip Filter peers by IP address
|
||||||
|
Ip *string `form:"ip,omitempty" json:"ip,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetApiPeersPeerIdIngressPortsParams defines parameters for GetApiPeersPeerIdIngressPorts.
|
||||||
|
type GetApiPeersPeerIdIngressPortsParams struct {
|
||||||
|
// Name Filters ingress port allocations by name
|
||||||
|
Name *string `form:"name,omitempty" json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetApiUsersParams defines parameters for GetApiUsers.
|
// GetApiUsersParams defines parameters for GetApiUsers.
|
||||||
type GetApiUsersParams struct {
|
type GetApiUsersParams struct {
|
||||||
// ServiceUser Filters users and returns either regular users or service users
|
// ServiceUser Filters users and returns either regular users or service users
|
||||||
@@ -1490,6 +1671,12 @@ type PostApiGroupsJSONRequestBody = GroupRequest
|
|||||||
// PutApiGroupsGroupIdJSONRequestBody defines body for PutApiGroupsGroupId for application/json ContentType.
|
// PutApiGroupsGroupIdJSONRequestBody defines body for PutApiGroupsGroupId for application/json ContentType.
|
||||||
type PutApiGroupsGroupIdJSONRequestBody = GroupRequest
|
type PutApiGroupsGroupIdJSONRequestBody = GroupRequest
|
||||||
|
|
||||||
|
// PostApiIngressPeersJSONRequestBody defines body for PostApiIngressPeers for application/json ContentType.
|
||||||
|
type PostApiIngressPeersJSONRequestBody = IngressPeerCreateRequest
|
||||||
|
|
||||||
|
// PutApiIngressPeersIngressPeerIdJSONRequestBody defines body for PutApiIngressPeersIngressPeerId for application/json ContentType.
|
||||||
|
type PutApiIngressPeersIngressPeerIdJSONRequestBody = IngressPeerUpdateRequest
|
||||||
|
|
||||||
// PostApiNetworksJSONRequestBody defines body for PostApiNetworks for application/json ContentType.
|
// PostApiNetworksJSONRequestBody defines body for PostApiNetworks for application/json ContentType.
|
||||||
type PostApiNetworksJSONRequestBody = NetworkRequest
|
type PostApiNetworksJSONRequestBody = NetworkRequest
|
||||||
|
|
||||||
@@ -1511,6 +1698,12 @@ type PutApiNetworksNetworkIdRoutersRouterIdJSONRequestBody = NetworkRouterReques
|
|||||||
// PutApiPeersPeerIdJSONRequestBody defines body for PutApiPeersPeerId for application/json ContentType.
|
// PutApiPeersPeerIdJSONRequestBody defines body for PutApiPeersPeerId for application/json ContentType.
|
||||||
type PutApiPeersPeerIdJSONRequestBody = PeerRequest
|
type PutApiPeersPeerIdJSONRequestBody = PeerRequest
|
||||||
|
|
||||||
|
// PostApiPeersPeerIdIngressPortsJSONRequestBody defines body for PostApiPeersPeerIdIngressPorts for application/json ContentType.
|
||||||
|
type PostApiPeersPeerIdIngressPortsJSONRequestBody = IngressPortAllocationRequest
|
||||||
|
|
||||||
|
// PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody defines body for PutApiPeersPeerIdIngressPortsAllocationId for application/json ContentType.
|
||||||
|
type PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody = IngressPortAllocationRequest
|
||||||
|
|
||||||
// PostApiPoliciesJSONRequestBody defines body for PostApiPolicies for application/json ContentType.
|
// PostApiPoliciesJSONRequestBody defines body for PostApiPolicies for application/json ContentType.
|
||||||
type PostApiPoliciesJSONRequestBody = PolicyUpdate
|
type PostApiPoliciesJSONRequestBody = PolicyUpdate
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ import (
|
|||||||
|
|
||||||
"github.com/netbirdio/management-integrations/integrations"
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/auth"
|
"github.com/netbirdio/netbird/management/server/auth"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||||
nbgroups "github.com/netbirdio/netbird/management/server/groups"
|
nbgroups "github.com/netbirdio/netbird/management/server/groups"
|
||||||
@@ -25,10 +30,11 @@ import (
|
|||||||
"github.com/netbirdio/netbird/management/server/http/handlers/setup_keys"
|
"github.com/netbirdio/netbird/management/server/http/handlers/setup_keys"
|
||||||
"github.com/netbirdio/netbird/management/server/http/handlers/users"
|
"github.com/netbirdio/netbird/management/server/http/handlers/users"
|
||||||
"github.com/netbirdio/netbird/management/server/http/middleware"
|
"github.com/netbirdio/netbird/management/server/http/middleware"
|
||||||
"github.com/netbirdio/netbird/management/server/integrated_validator"
|
"github.com/netbirdio/netbird/management/server/integrations/integrated_validator"
|
||||||
nbnetworks "github.com/netbirdio/netbird/management/server/networks"
|
nbnetworks "github.com/netbirdio/netbird/management/server/networks"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||||
|
nbpeers "github.com/netbirdio/netbird/management/server/peers"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,7 +43,7 @@ const apiPrefix = "/api"
|
|||||||
// NewAPIHandler creates the Management service HTTP API handler registering all the available endpoints.
|
// NewAPIHandler creates the Management service HTTP API handler registering all the available endpoints.
|
||||||
func NewAPIHandler(
|
func NewAPIHandler(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
accountManager s.AccountManager,
|
accountManager account.AccountManager,
|
||||||
networksManager nbnetworks.Manager,
|
networksManager nbnetworks.Manager,
|
||||||
resourceManager resources.Manager,
|
resourceManager resources.Manager,
|
||||||
routerManager routers.Manager,
|
routerManager routers.Manager,
|
||||||
@@ -45,8 +51,12 @@ func NewAPIHandler(
|
|||||||
LocationManager geolocation.Geolocation,
|
LocationManager geolocation.Geolocation,
|
||||||
authManager auth.Manager,
|
authManager auth.Manager,
|
||||||
appMetrics telemetry.AppMetrics,
|
appMetrics telemetry.AppMetrics,
|
||||||
config *s.Config,
|
integratedValidator integrated_validator.IntegratedValidator,
|
||||||
integratedValidator integrated_validator.IntegratedValidator) (http.Handler, error) {
|
proxyController port_forwarding.Controller,
|
||||||
|
permissionsManager permissions.Manager,
|
||||||
|
peersManager nbpeers.Manager,
|
||||||
|
settingsManager settings.Manager,
|
||||||
|
) (http.Handler, error) {
|
||||||
|
|
||||||
authMiddleware := middleware.NewAuthMiddleware(
|
authMiddleware := middleware.NewAuthMiddleware(
|
||||||
authManager,
|
authManager,
|
||||||
@@ -66,11 +76,11 @@ func NewAPIHandler(
|
|||||||
|
|
||||||
router.Use(metricsMiddleware.Handler, corsMiddleware.Handler, authMiddleware.Handler, acMiddleware.Handler)
|
router.Use(metricsMiddleware.Handler, corsMiddleware.Handler, authMiddleware.Handler, acMiddleware.Handler)
|
||||||
|
|
||||||
if _, err := integrations.RegisterHandlers(ctx, prefix, router, accountManager, integratedValidator, appMetrics.GetMeter()); err != nil {
|
if _, err := integrations.RegisterHandlers(ctx, prefix, router, accountManager, integratedValidator, appMetrics.GetMeter(), permissionsManager, peersManager, proxyController, settingsManager); err != nil {
|
||||||
return nil, fmt.Errorf("register integrations endpoints: %w", err)
|
return nil, fmt.Errorf("register integrations endpoints: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
accounts.AddEndpoints(accountManager, router)
|
accounts.AddEndpoints(accountManager, settingsManager, router)
|
||||||
peers.AddEndpoints(accountManager, router)
|
peers.AddEndpoints(accountManager, router)
|
||||||
users.AddEndpoints(accountManager, router)
|
users.AddEndpoints(accountManager, router)
|
||||||
setup_keys.AddEndpoints(accountManager, router)
|
setup_keys.AddEndpoints(accountManager, router)
|
||||||
|
|||||||
@@ -7,31 +7,33 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// handler is a handler that handles the server.Account HTTP endpoints
|
// handler is a handler that handles the server.Account HTTP endpoints
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
|
settingsManager settings.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, settingsManager settings.Manager, router *mux.Router) {
|
||||||
accountsHandler := newHandler(accountManager)
|
accountsHandler := newHandler(accountManager, settingsManager)
|
||||||
router.HandleFunc("/accounts/{accountId}", accountsHandler.updateAccount).Methods("PUT", "OPTIONS")
|
router.HandleFunc("/accounts/{accountId}", accountsHandler.updateAccount).Methods("PUT", "OPTIONS")
|
||||||
router.HandleFunc("/accounts/{accountId}", accountsHandler.deleteAccount).Methods("DELETE", "OPTIONS")
|
router.HandleFunc("/accounts/{accountId}", accountsHandler.deleteAccount).Methods("DELETE", "OPTIONS")
|
||||||
router.HandleFunc("/accounts", accountsHandler.getAllAccounts).Methods("GET", "OPTIONS")
|
router.HandleFunc("/accounts", accountsHandler.getAllAccounts).Methods("GET", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new handler HTTP handler
|
// newHandler creates a new handler HTTP handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager, settingsManager settings.Manager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
|
settingsManager: settingsManager,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +47,7 @@ func (h *handler) getAllAccounts(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
accountID, userID := userAuth.AccountId, userAuth.UserId
|
accountID, userID := userAuth.AccountId, userAuth.UserId
|
||||||
|
|
||||||
settings, err := h.accountManager.GetAccountSettings(r.Context(), accountID, userID)
|
settings, err := h.settingsManager.GetSettings(r.Context(), accountID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
@@ -89,7 +91,14 @@ func (h *handler) updateAccount(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if req.Settings.Extra != nil {
|
if req.Settings.Extra != nil {
|
||||||
settings.Extra = &account.ExtraSettings{PeerApprovalEnabled: *req.Settings.Extra.PeerApprovalEnabled}
|
flowEnabled := false
|
||||||
|
if req.Settings.Extra.NetworkTrafficLogsEnabled != nil {
|
||||||
|
flowEnabled = *req.Settings.Extra.NetworkTrafficLogsEnabled
|
||||||
|
}
|
||||||
|
settings.Extra = &types.ExtraSettings{
|
||||||
|
PeerApprovalEnabled: *req.Settings.Extra.PeerApprovalEnabled,
|
||||||
|
FlowEnabled: flowEnabled,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Settings.JwtGroupsEnabled != nil {
|
if req.Settings.JwtGroupsEnabled != nil {
|
||||||
@@ -163,7 +172,10 @@ func toAccountResponse(accountID string, settings *types.Settings) *api.Account
|
|||||||
}
|
}
|
||||||
|
|
||||||
if settings.Extra != nil {
|
if settings.Extra != nil {
|
||||||
apiSettings.Extra = &api.AccountExtraSettings{PeerApprovalEnabled: &settings.Extra.PeerApprovalEnabled}
|
apiSettings.Extra = &api.AccountExtraSettings{
|
||||||
|
PeerApprovalEnabled: &settings.Extra.PeerApprovalEnabled,
|
||||||
|
NetworkTrafficLogsEnabled: &settings.Extra.FlowEnabled,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &api.Account{
|
return &api.Account{
|
||||||
|
|||||||
@@ -16,11 +16,16 @@ import (
|
|||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initAccountsTestData(account *types.Account) *handler {
|
func initAccountsTestData(account *types.Account) *handler {
|
||||||
|
settingsMock := settings.NewManagerMock()
|
||||||
|
settingsMock.GetSettingsFunc = func(ctx context.Context, accountID string, userID string) (*types.Settings, error) {
|
||||||
|
return account.Settings, nil
|
||||||
|
}
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: &mock_server.MockAccountManager{
|
accountManager: &mock_server.MockAccountManager{
|
||||||
GetAccountSettingsFunc: func(ctx context.Context, accountID string, userID string) (*types.Settings, error) {
|
GetAccountSettingsFunc: func(ctx context.Context, accountID string, userID string) (*types.Settings, error) {
|
||||||
@@ -41,6 +46,7 @@ func initAccountsTestData(account *types.Account) *handler {
|
|||||||
return accCopy, nil
|
return accCopy, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
settingsManager: settingsMock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
@@ -16,22 +16,22 @@ import (
|
|||||||
|
|
||||||
// dnsSettingsHandler is a handler that returns the DNS settings of the account
|
// dnsSettingsHandler is a handler that returns the DNS settings of the account
|
||||||
type dnsSettingsHandler struct {
|
type dnsSettingsHandler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
addDNSSettingEndpoint(accountManager, router)
|
addDNSSettingEndpoint(accountManager, router)
|
||||||
addDNSNameserversEndpoint(accountManager, router)
|
addDNSNameserversEndpoint(accountManager, router)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDNSSettingEndpoint(accountManager server.AccountManager, router *mux.Router) {
|
func addDNSSettingEndpoint(accountManager account.AccountManager, router *mux.Router) {
|
||||||
dnsSettingsHandler := newDNSSettingsHandler(accountManager)
|
dnsSettingsHandler := newDNSSettingsHandler(accountManager)
|
||||||
router.HandleFunc("/dns/settings", dnsSettingsHandler.getDNSSettings).Methods("GET", "OPTIONS")
|
router.HandleFunc("/dns/settings", dnsSettingsHandler.getDNSSettings).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/dns/settings", dnsSettingsHandler.updateDNSSettings).Methods("PUT", "OPTIONS")
|
router.HandleFunc("/dns/settings", dnsSettingsHandler.updateDNSSettings).Methods("PUT", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// newDNSSettingsHandler returns a new instance of dnsSettingsHandler handler
|
// newDNSSettingsHandler returns a new instance of dnsSettingsHandler handler
|
||||||
func newDNSSettingsHandler(accountManager server.AccountManager) *dnsSettingsHandler {
|
func newDNSSettingsHandler(accountManager account.AccountManager) *dnsSettingsHandler {
|
||||||
return &dnsSettingsHandler{accountManager: accountManager}
|
return &dnsSettingsHandler{accountManager: accountManager}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
@@ -18,10 +18,10 @@ import (
|
|||||||
|
|
||||||
// nameserversHandler is the nameserver group handler of the account
|
// nameserversHandler is the nameserver group handler of the account
|
||||||
type nameserversHandler struct {
|
type nameserversHandler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func addDNSNameserversEndpoint(accountManager server.AccountManager, router *mux.Router) {
|
func addDNSNameserversEndpoint(accountManager account.AccountManager, router *mux.Router) {
|
||||||
nameserversHandler := newNameserversHandler(accountManager)
|
nameserversHandler := newNameserversHandler(accountManager)
|
||||||
router.HandleFunc("/dns/nameservers", nameserversHandler.getAllNameservers).Methods("GET", "OPTIONS")
|
router.HandleFunc("/dns/nameservers", nameserversHandler.getAllNameservers).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/dns/nameservers", nameserversHandler.createNameserverGroup).Methods("POST", "OPTIONS")
|
router.HandleFunc("/dns/nameservers", nameserversHandler.createNameserverGroup).Methods("POST", "OPTIONS")
|
||||||
@@ -31,7 +31,7 @@ func addDNSNameserversEndpoint(accountManager server.AccountManager, router *mux
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newNameserversHandler returns a new instance of nameserversHandler handler
|
// newNameserversHandler returns a new instance of nameserversHandler handler
|
||||||
func newNameserversHandler(accountManager server.AccountManager) *nameserversHandler {
|
func newNameserversHandler(accountManager account.AccountManager) *nameserversHandler {
|
||||||
return &nameserversHandler{accountManager: accountManager}
|
return &nameserversHandler{accountManager: accountManager}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -17,16 +17,16 @@ import (
|
|||||||
|
|
||||||
// handler HTTP handler
|
// handler HTTP handler
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
eventsHandler := newHandler(accountManager)
|
eventsHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/events", eventsHandler.getAllEvents).Methods("GET", "OPTIONS")
|
router.HandleFunc("/events", eventsHandler.getAllEvents).Methods("GET", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new events handler
|
// newHandler creates a new events handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{accountManager: accountManager}
|
return &handler{accountManager: accountManager}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
@@ -19,10 +19,10 @@ import (
|
|||||||
|
|
||||||
// handler is a handler that returns groups of the account
|
// handler is a handler that returns groups of the account
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
groupsHandler := newHandler(accountManager)
|
groupsHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/groups", groupsHandler.getAllGroups).Methods("GET", "OPTIONS")
|
router.HandleFunc("/groups", groupsHandler.getAllGroups).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/groups", groupsHandler.createGroup).Methods("POST", "OPTIONS")
|
router.HandleFunc("/groups", groupsHandler.createGroup).Methods("POST", "OPTIONS")
|
||||||
@@ -32,7 +32,7 @@ func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new groups handler
|
// newHandler creates a new groups handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func (h *handler) getAllGroups(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID)
|
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
@@ -149,7 +149,7 @@ func (h *handler) updateGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID)
|
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
@@ -209,7 +209,7 @@ func (h *handler) createGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID)
|
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
@@ -270,7 +270,7 @@ func (h *handler) getGroup(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID)
|
accountPeers, err := h.accountManager.GetPeers(r.Context(), accountID, userID, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func initGroupTestData(initGroups ...*types.Group) *handler {
|
|||||||
|
|
||||||
return nil, fmt.Errorf("unknown group name")
|
return nil, fmt.Errorf("unknown group name")
|
||||||
},
|
},
|
||||||
GetPeersFunc: func(ctx context.Context, accountID, userID string) ([]*nbpeer.Peer, error) {
|
GetPeersFunc: func(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error) {
|
||||||
return maps.Values(TestPeers), nil
|
return maps.Values(TestPeers), nil
|
||||||
},
|
},
|
||||||
DeleteGroupFunc: func(_ context.Context, accountID, userId, groupID string) error {
|
DeleteGroupFunc: func(_ context.Context, accountID, userId, groupID string) error {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/groups"
|
"github.com/netbirdio/netbird/management/server/groups"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -28,12 +28,12 @@ type handler struct {
|
|||||||
networksManager networks.Manager
|
networksManager networks.Manager
|
||||||
resourceManager resources.Manager
|
resourceManager resources.Manager
|
||||||
routerManager routers.Manager
|
routerManager routers.Manager
|
||||||
accountManager s.AccountManager
|
accountManager account.AccountManager
|
||||||
|
|
||||||
groupsManager groups.Manager
|
groupsManager groups.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(networksManager networks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager groups.Manager, accountManager s.AccountManager, router *mux.Router) {
|
func AddEndpoints(networksManager networks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager groups.Manager, accountManager account.AccountManager, router *mux.Router) {
|
||||||
addRouterEndpoints(routerManager, router)
|
addRouterEndpoints(routerManager, router)
|
||||||
addResourceEndpoints(resourceManager, groupsManager, router)
|
addResourceEndpoints(resourceManager, groupsManager, router)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ func AddEndpoints(networksManager networks.Manager, resourceManager resources.Ma
|
|||||||
router.HandleFunc("/networks/{networkId}", networksHandler.deleteNetwork).Methods("DELETE", "OPTIONS")
|
router.HandleFunc("/networks/{networkId}", networksHandler.deleteNetwork).Methods("DELETE", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHandler(networksManager networks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager groups.Manager, accountManager s.AccountManager) *handler {
|
func newHandler(networksManager networks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager groups.Manager, accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
networksManager: networksManager,
|
networksManager: networksManager,
|
||||||
resourceManager: resourceManager,
|
resourceManager: resourceManager,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/groups"
|
"github.com/netbirdio/netbird/management/server/groups"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -21,10 +21,10 @@ import (
|
|||||||
|
|
||||||
// Handler is a handler that returns peers of the account
|
// Handler is a handler that returns peers of the account
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
peersHandler := NewHandler(accountManager)
|
peersHandler := NewHandler(accountManager)
|
||||||
router.HandleFunc("/peers", peersHandler.GetAllPeers).Methods("GET", "OPTIONS")
|
router.HandleFunc("/peers", peersHandler.GetAllPeers).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/peers/{peerId}", peersHandler.HandlePeer).
|
router.HandleFunc("/peers/{peerId}", peersHandler.HandlePeer).
|
||||||
@@ -33,7 +33,7 @@ func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a new peers Handler
|
// NewHandler creates a new peers Handler
|
||||||
func NewHandler(accountManager server.AccountManager) *Handler {
|
func NewHandler(accountManager account.AccountManager) *Handler {
|
||||||
return &Handler{
|
return &Handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,12 @@ func (h *Handler) GetAllPeers(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nameFilter := r.URL.Query().Get("name")
|
||||||
|
ipFilter := r.URL.Query().Get("ip")
|
||||||
|
|
||||||
accountID, userID := userAuth.AccountId, userAuth.UserId
|
accountID, userID := userAuth.AccountId, userAuth.UserId
|
||||||
|
|
||||||
peers, err := h.accountManager.GetPeers(r.Context(), accountID, userID)
|
peers, err := h.accountManager.GetPeers(r.Context(), accountID, userID, nameFilter, ipFilter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
util.WriteError(r.Context(), err, w)
|
util.WriteError(r.Context(), err, w)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func initTestMetaData(peers ...*nbpeer.Peer) *Handler {
|
|||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
},
|
},
|
||||||
GetPeersFunc: func(_ context.Context, accountID, userID string) ([]*nbpeer.Peer, error) {
|
GetPeersFunc: func(_ context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error) {
|
||||||
return peers, nil
|
return peers, nil
|
||||||
},
|
},
|
||||||
GetPeerGroupsFunc: func(ctx context.Context, accountID, peerID string) ([]*types.Group, error) {
|
GetPeerGroupsFunc: func(ctx context.Context, accountID, peerID string) ([]*types.Group, error) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -20,18 +20,18 @@ var (
|
|||||||
|
|
||||||
// geolocationsHandler is a handler that returns locations.
|
// geolocationsHandler is a handler that returns locations.
|
||||||
type geolocationsHandler struct {
|
type geolocationsHandler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
geolocationManager geolocation.Geolocation
|
geolocationManager geolocation.Geolocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func addLocationsEndpoint(accountManager server.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
func addLocationsEndpoint(accountManager account.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
||||||
locationHandler := newGeolocationsHandlerHandler(accountManager, locationManager)
|
locationHandler := newGeolocationsHandlerHandler(accountManager, locationManager)
|
||||||
router.HandleFunc("/locations/countries", locationHandler.getAllCountries).Methods("GET", "OPTIONS")
|
router.HandleFunc("/locations/countries", locationHandler.getAllCountries).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/locations/countries/{country}/cities", locationHandler.getCitiesByCountry).Methods("GET", "OPTIONS")
|
router.HandleFunc("/locations/countries/{country}/cities", locationHandler.getCitiesByCountry).Methods("GET", "OPTIONS")
|
||||||
}
|
}
|
||||||
|
|
||||||
// newGeolocationsHandlerHandler creates a new Geolocations handler
|
// newGeolocationsHandlerHandler creates a new Geolocations handler
|
||||||
func newGeolocationsHandlerHandler(accountManager server.AccountManager, geolocationManager geolocation.Geolocation) *geolocationsHandler {
|
func newGeolocationsHandlerHandler(accountManager account.AccountManager, geolocationManager geolocation.Geolocation) *geolocationsHandler {
|
||||||
return &geolocationsHandler{
|
return &geolocationsHandler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
geolocationManager: geolocationManager,
|
geolocationManager: geolocationManager,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -18,10 +18,10 @@ import (
|
|||||||
|
|
||||||
// handler is a handler that returns policy of the account
|
// handler is a handler that returns policy of the account
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
||||||
policiesHandler := newHandler(accountManager)
|
policiesHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/policies", policiesHandler.getAllPolicies).Methods("GET", "OPTIONS")
|
router.HandleFunc("/policies", policiesHandler.getAllPolicies).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/policies", policiesHandler.createPolicy).Methods("POST", "OPTIONS")
|
router.HandleFunc("/policies", policiesHandler.createPolicy).Methods("POST", "OPTIONS")
|
||||||
@@ -32,7 +32,7 @@ func AddEndpoints(accountManager server.AccountManager, locationManager geolocat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new policies handler
|
// newHandler creates a new policies handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
@@ -17,11 +17,11 @@ import (
|
|||||||
|
|
||||||
// postureChecksHandler is a handler that returns posture checks of the account.
|
// postureChecksHandler is a handler that returns posture checks of the account.
|
||||||
type postureChecksHandler struct {
|
type postureChecksHandler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
geolocationManager geolocation.Geolocation
|
geolocationManager geolocation.Geolocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func addPostureCheckEndpoint(accountManager server.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
func addPostureCheckEndpoint(accountManager account.AccountManager, locationManager geolocation.Geolocation, router *mux.Router) {
|
||||||
postureCheckHandler := newPostureChecksHandler(accountManager, locationManager)
|
postureCheckHandler := newPostureChecksHandler(accountManager, locationManager)
|
||||||
router.HandleFunc("/posture-checks", postureCheckHandler.getAllPostureChecks).Methods("GET", "OPTIONS")
|
router.HandleFunc("/posture-checks", postureCheckHandler.getAllPostureChecks).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/posture-checks", postureCheckHandler.createPostureCheck).Methods("POST", "OPTIONS")
|
router.HandleFunc("/posture-checks", postureCheckHandler.createPostureCheck).Methods("POST", "OPTIONS")
|
||||||
@@ -32,7 +32,7 @@ func addPostureCheckEndpoint(accountManager server.AccountManager, locationManag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newPostureChecksHandler creates a new PostureChecks handler
|
// newPostureChecksHandler creates a new PostureChecks handler
|
||||||
func newPostureChecksHandler(accountManager server.AccountManager, geolocationManager geolocation.Geolocation) *postureChecksHandler {
|
func newPostureChecksHandler(accountManager account.AccountManager, geolocationManager geolocation.Geolocation) *postureChecksHandler {
|
||||||
return &postureChecksHandler{
|
return &postureChecksHandler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
geolocationManager: geolocationManager,
|
geolocationManager: geolocationManager,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/domain"
|
"github.com/netbirdio/netbird/management/domain"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
@@ -21,10 +21,10 @@ const failedToConvertRoute = "failed to convert route to response: %v"
|
|||||||
|
|
||||||
// handler is the routes handler of the account
|
// handler is the routes handler of the account
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
routesHandler := newHandler(accountManager)
|
routesHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/routes", routesHandler.getAllRoutes).Methods("GET", "OPTIONS")
|
router.HandleFunc("/routes", routesHandler.getAllRoutes).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/routes", routesHandler.createRoute).Methods("POST", "OPTIONS")
|
router.HandleFunc("/routes", routesHandler.createRoute).Methods("POST", "OPTIONS")
|
||||||
@@ -34,7 +34,7 @@ func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newHandler returns a new instance of routes handler
|
// newHandler returns a new instance of routes handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ package setup_keys
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
@@ -19,10 +18,10 @@ import (
|
|||||||
|
|
||||||
// handler is a handler that returns a list of setup keys of the account
|
// handler is a handler that returns a list of setup keys of the account
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
keysHandler := newHandler(accountManager)
|
keysHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/setup-keys", keysHandler.getAllSetupKeys).Methods("GET", "OPTIONS")
|
router.HandleFunc("/setup-keys", keysHandler.getAllSetupKeys).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/setup-keys", keysHandler.createSetupKey).Methods("POST", "OPTIONS")
|
router.HandleFunc("/setup-keys", keysHandler.createSetupKey).Methods("POST", "OPTIONS")
|
||||||
@@ -32,7 +31,7 @@ func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new setup key handler
|
// newHandler creates a new setup key handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
@@ -16,10 +16,10 @@ import (
|
|||||||
|
|
||||||
// patHandler is the nameserver group handler of the account
|
// patHandler is the nameserver group handler of the account
|
||||||
type patHandler struct {
|
type patHandler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func addUsersTokensEndpoint(accountManager server.AccountManager, router *mux.Router) {
|
func addUsersTokensEndpoint(accountManager account.AccountManager, router *mux.Router) {
|
||||||
tokenHandler := newPATsHandler(accountManager)
|
tokenHandler := newPATsHandler(accountManager)
|
||||||
router.HandleFunc("/users/{userId}/tokens", tokenHandler.getAllTokens).Methods("GET", "OPTIONS")
|
router.HandleFunc("/users/{userId}/tokens", tokenHandler.getAllTokens).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/users/{userId}/tokens", tokenHandler.createToken).Methods("POST", "OPTIONS")
|
router.HandleFunc("/users/{userId}/tokens", tokenHandler.createToken).Methods("POST", "OPTIONS")
|
||||||
@@ -28,7 +28,7 @@ func addUsersTokensEndpoint(accountManager server.AccountManager, router *mux.Ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newPATsHandler creates a new patHandler HTTP handler
|
// newPATsHandler creates a new patHandler HTTP handler
|
||||||
func newPATsHandler(accountManager server.AccountManager) *patHandler {
|
func newPATsHandler(accountManager account.AccountManager) *patHandler {
|
||||||
return &patHandler{
|
return &patHandler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,21 +8,21 @@ import (
|
|||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/http/api"
|
"github.com/netbirdio/netbird/management/server/http/api"
|
||||||
"github.com/netbirdio/netbird/management/server/http/util"
|
"github.com/netbirdio/netbird/management/server/http/util"
|
||||||
"github.com/netbirdio/netbird/management/server/status"
|
"github.com/netbirdio/netbird/management/server/status"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
// handler is a handler that returns users of the account
|
// handler is a handler that returns users of the account
|
||||||
type handler struct {
|
type handler struct {
|
||||||
accountManager server.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
func AddEndpoints(accountManager account.AccountManager, router *mux.Router) {
|
||||||
userHandler := newHandler(accountManager)
|
userHandler := newHandler(accountManager)
|
||||||
router.HandleFunc("/users", userHandler.getAllUsers).Methods("GET", "OPTIONS")
|
router.HandleFunc("/users", userHandler.getAllUsers).Methods("GET", "OPTIONS")
|
||||||
router.HandleFunc("/users/{userId}", userHandler.updateUser).Methods("PUT", "OPTIONS")
|
router.HandleFunc("/users/{userId}", userHandler.updateUser).Methods("PUT", "OPTIONS")
|
||||||
@@ -33,7 +33,7 @@ func AddEndpoints(accountManager server.AccountManager, router *mux.Router) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newHandler creates a new UsersHandler HTTP handler
|
// newHandler creates a new UsersHandler HTTP handler
|
||||||
func newHandler(accountManager server.AccountManager) *handler {
|
func newHandler(accountManager account.AccountManager) *handler {
|
||||||
return &handler{
|
return &handler{
|
||||||
accountManager: accountManager,
|
accountManager: accountManager,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,19 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
"github.com/golang-jwt/jwt"
|
||||||
|
|
||||||
|
"github.com/netbirdio/management-integrations/integrations"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
|
"github.com/netbirdio/netbird/management/server/users"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/peers"
|
||||||
|
"github.com/netbirdio/netbird/management/server/permissions"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/auth"
|
"github.com/netbirdio/netbird/management/server/auth"
|
||||||
@@ -84,7 +94,7 @@ type PerformanceMetrics struct {
|
|||||||
MaxMsPerOpCICD float64
|
MaxMsPerOpCICD float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *server.UpdateMessage, validateUpdate bool) (http.Handler, server.AccountManager, chan struct{}) {
|
func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *server.UpdateMessage, validateUpdate bool) (http.Handler, account.AccountManager, chan struct{}) {
|
||||||
store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), sqlFile, t.TempDir())
|
store, cleanup, err := store.NewTestStoreFromSQL(context.Background(), sqlFile, t.TempDir())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create test store: %v", err)
|
t.Fatalf("Failed to create test store: %v", err)
|
||||||
@@ -112,7 +122,10 @@ func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *serve
|
|||||||
|
|
||||||
geoMock := &geolocation.Mock{}
|
geoMock := &geolocation.Mock{}
|
||||||
validatorMock := server.MocIntegratedValidator{}
|
validatorMock := server.MocIntegratedValidator{}
|
||||||
am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics)
|
proxyController := integrations.NewController(store)
|
||||||
|
userManager := users.NewManager(store)
|
||||||
|
settingsManager := settings.NewManager(store, userManager, integrations.NewManager())
|
||||||
|
am, err := server.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "", &activity.InMemoryEventStore{}, geoMock, false, validatorMock, metrics, proxyController, settingsManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create manager: %v", err)
|
t.Fatalf("Failed to create manager: %v", err)
|
||||||
}
|
}
|
||||||
@@ -130,7 +143,10 @@ func BuildApiBlackBoxWithDBState(t TB, sqlFile string, expectedPeerUpdate *serve
|
|||||||
resourcesManagerMock := resources.NewManagerMock()
|
resourcesManagerMock := resources.NewManagerMock()
|
||||||
routersManagerMock := routers.NewManagerMock()
|
routersManagerMock := routers.NewManagerMock()
|
||||||
groupsManagerMock := groups.NewManagerMock()
|
groupsManagerMock := groups.NewManagerMock()
|
||||||
apiHandler, err := nbhttp.NewAPIHandler(context.Background(), am, networksManagerMock, resourcesManagerMock, routersManagerMock, groupsManagerMock, geoMock, authManagerMock, metrics, &server.Config{}, validatorMock)
|
permissionsManagerMock := permissions.NewManagerMock()
|
||||||
|
peersManager := peers.NewManager(store, permissionsManagerMock)
|
||||||
|
|
||||||
|
apiHandler, err := nbhttp.NewAPIHandler(context.Background(), am, networksManagerMock, resourcesManagerMock, routersManagerMock, groupsManagerMock, geoMock, authManagerMock, metrics, validatorMock, proxyController, permissionsManagerMock, peersManager, settingsManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create API handler: %v", err)
|
t.Fatalf("Failed to create API handler: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
@@ -43,12 +42,12 @@ func (am *DefaultAccountManager) UpdateIntegratedValidatorGroups(ctx context.Con
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var extra *account.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 = &account.ExtraSettings{}
|
extra = &types.ExtraSettings{}
|
||||||
a.Settings.Extra = extra
|
a.Settings.Extra = extra
|
||||||
}
|
}
|
||||||
extra.IntegratedValidatorGroups = groups
|
extra.IntegratedValidatorGroups = groups
|
||||||
@@ -88,7 +87,7 @@ func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountI
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
peers, err = transaction.GetAccountPeers(ctx, store.LockingStrengthShare, accountID)
|
peers, err = transaction.GetAccountPeers(ctx, store.LockingStrengthShare, accountID, "", "")
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -104,21 +103,21 @@ func (am *DefaultAccountManager) GetValidatedPeers(ctx context.Context, accountI
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MocIntegratedValidator struct {
|
type MocIntegratedValidator struct {
|
||||||
ValidatePeerFunc func(_ context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool, error)
|
ValidatePeerFunc func(_ context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *types.ExtraSettings) (*nbpeer.Peer, bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a MocIntegratedValidator) ValidateExtraSettings(_ context.Context, newExtraSettings *account.ExtraSettings, oldExtraSettings *account.ExtraSettings, peers map[string]*nbpeer.Peer, userID string, accountID string) error {
|
func (a MocIntegratedValidator) ValidateExtraSettings(_ context.Context, newExtraSettings *types.ExtraSettings, oldExtraSettings *types.ExtraSettings, peers map[string]*nbpeer.Peer, userID string, accountID string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a MocIntegratedValidator) ValidatePeer(_ context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool, error) {
|
func (a MocIntegratedValidator) ValidatePeer(_ context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *types.ExtraSettings) (*nbpeer.Peer, bool, error) {
|
||||||
if a.ValidatePeerFunc != nil {
|
if a.ValidatePeerFunc != nil {
|
||||||
return a.ValidatePeerFunc(context.Background(), update, peer, userID, accountID, dnsDomain, peersGroup, extraSettings)
|
return a.ValidatePeerFunc(context.Background(), update, peer, userID, accountID, dnsDomain, peersGroup, extraSettings)
|
||||||
}
|
}
|
||||||
return update, false, nil
|
return update, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a MocIntegratedValidator) GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *account.ExtraSettings) (map[string]struct{}, error) {
|
func (a MocIntegratedValidator) GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error) {
|
||||||
validatedPeers := make(map[string]struct{})
|
validatedPeers := make(map[string]struct{})
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
validatedPeers[peer.ID] = struct{}{}
|
validatedPeers[peer.ID] = struct{}{}
|
||||||
@@ -126,11 +125,11 @@ func (a MocIntegratedValidator) GetValidatedPeers(accountID string, groups []*ty
|
|||||||
return validatedPeers, nil
|
return validatedPeers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MocIntegratedValidator) PreparePeer(_ context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) *nbpeer.Peer {
|
func (MocIntegratedValidator) PreparePeer(_ context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) *nbpeer.Peer {
|
||||||
return peer
|
return peer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (MocIntegratedValidator) IsNotValidPeer(_ context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (bool, bool, error) {
|
func (MocIntegratedValidator) IsNotValidPeer(_ context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) (bool, bool, error) {
|
||||||
return false, false, nil
|
return false, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
management/server/integrations/extra_settings/manager.go
Normal file
12
management/server/integrations/extra_settings/manager.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package extra_settings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Manager interface {
|
||||||
|
GetExtraSettings(ctx context.Context, accountID string) (*types.ExtraSettings, error)
|
||||||
|
UpdateExtraSettings(ctx context.Context, accountID string, extraSettings *types.ExtraSettings) error
|
||||||
|
}
|
||||||
@@ -3,18 +3,17 @@ package integrated_validator
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/management/server/account"
|
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IntegratedValidator interface exists to avoid the circle dependencies
|
// IntegratedValidator interface exists to avoid the circle dependencies
|
||||||
type IntegratedValidator interface {
|
type IntegratedValidator interface {
|
||||||
ValidateExtraSettings(ctx context.Context, newExtraSettings *account.ExtraSettings, oldExtraSettings *account.ExtraSettings, peers map[string]*nbpeer.Peer, userID string, accountID string) error
|
ValidateExtraSettings(ctx context.Context, newExtraSettings *types.ExtraSettings, oldExtraSettings *types.ExtraSettings, peers map[string]*nbpeer.Peer, userID string, accountID string) error
|
||||||
ValidatePeer(ctx context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *account.ExtraSettings) (*nbpeer.Peer, bool, error)
|
ValidatePeer(ctx context.Context, update *nbpeer.Peer, peer *nbpeer.Peer, userID string, accountID string, dnsDomain string, peersGroup []string, extraSettings *types.ExtraSettings) (*nbpeer.Peer, bool, error)
|
||||||
PreparePeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) *nbpeer.Peer
|
PreparePeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) *nbpeer.Peer
|
||||||
IsNotValidPeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *account.ExtraSettings) (bool, bool, error)
|
IsNotValidPeer(ctx context.Context, accountID string, peer *nbpeer.Peer, peersGroup []string, extraSettings *types.ExtraSettings) (bool, bool, error)
|
||||||
GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *account.ExtraSettings) (map[string]struct{}, error)
|
GetValidatedPeers(accountID string, groups []*types.Group, peers []*nbpeer.Peer, extraSettings *types.ExtraSettings) (map[string]struct{}, error)
|
||||||
PeerDeleted(ctx context.Context, accountID, peerID string) error
|
PeerDeleted(ctx context.Context, accountID, peerID string) error
|
||||||
SetPeerInvalidationListener(fn func(accountID string))
|
SetPeerInvalidationListener(fn func(accountID string))
|
||||||
Stop(ctx context.Context)
|
Stop(ctx context.Context)
|
||||||
27
management/server/integrations/port_forwarding/controller.go
Normal file
27
management/server/integrations/port_forwarding/controller.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package port_forwarding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
nbtypes "github.com/netbirdio/netbird/management/server/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Controller interface {
|
||||||
|
SendUpdate(ctx context.Context, accountID string, affectedProxyID string, affectedPeerIDs []string)
|
||||||
|
GetProxyNetworkMaps(ctx context.Context, accountID string) (map[string]*nbtypes.NetworkMap, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ControllerMock struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewControllerMock() *ControllerMock {
|
||||||
|
return &ControllerMock{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ControllerMock) SendUpdate(ctx context.Context, accountID string, affectedProxyID string, affectedPeerIDs []string) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ControllerMock) GetProxyNetworkMaps(ctx context.Context, accountID string) (map[string]*nbtypes.NetworkMap, error) {
|
||||||
|
return make(map[string]*nbtypes.NetworkMap), nil
|
||||||
|
}
|
||||||
@@ -22,7 +22,9 @@ import (
|
|||||||
"github.com/netbirdio/netbird/encryption"
|
"github.com/netbirdio/netbird/encryption"
|
||||||
"github.com/netbirdio/netbird/formatter"
|
"github.com/netbirdio/netbird/formatter"
|
||||||
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
||||||
|
nbAccount "github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -430,7 +432,7 @@ func startManagementForTest(t *testing.T, testFile string, config *Config) (*grp
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
accountManager, err := BuildManager(ctx, store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
accountManager, err := BuildManager(ctx, store, peersUpdateManager, nil, "", "netbird.selfhosted",
|
||||||
eventStore, nil, false, MocIntegratedValidator{}, metrics)
|
eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cleanup()
|
cleanup()
|
||||||
@@ -440,7 +442,7 @@ func startManagementForTest(t *testing.T, testFile string, config *Config) (*grp
|
|||||||
secretsManager := NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
secretsManager := NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay)
|
||||||
|
|
||||||
ephemeralMgr := NewEphemeralManager(store, accountManager)
|
ephemeralMgr := NewEphemeralManager(store, accountManager)
|
||||||
mgmtServer, err := NewServer(context.Background(), config, accountManager, settings.NewManager(store), peersUpdateManager, secretsManager, nil, ephemeralMgr, nil)
|
mgmtServer, err := NewServer(context.Background(), config, accountManager, settings.NewManagerMock(), peersUpdateManager, secretsManager, nil, ephemeralMgr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", cleanup, err
|
return nil, nil, "", cleanup, err
|
||||||
}
|
}
|
||||||
@@ -739,7 +741,7 @@ func Test_LoginPerformance(t *testing.T) {
|
|||||||
NetbirdVersion: "",
|
NetbirdVersion: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
peerLogin := PeerLogin{
|
peerLogin := nbAccount.PeerLogin{
|
||||||
WireGuardPubKey: key.String(),
|
WireGuardPubKey: key.String(),
|
||||||
SSHKey: "random",
|
SSHKey: "random",
|
||||||
Meta: extractPeerMeta(context.Background(), meta),
|
Meta: extractPeerMeta(context.Background(), meta),
|
||||||
@@ -764,7 +766,7 @@ func Test_LoginPerformance(t *testing.T) {
|
|||||||
messageCalls = append(messageCalls, login)
|
messageCalls = append(messageCalls, login)
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
|
|
||||||
go func(peerLogin PeerLogin, counterStart *int32) {
|
go func(peerLogin nbAccount.PeerLogin, counterStart *int32) {
|
||||||
defer wgPeer.Done()
|
defer wgPeer.Done()
|
||||||
_, _, _, err = am.LoginPeer(context.Background(), peerLogin)
|
_, _, _, err = am.LoginPeer(context.Background(), peerLogin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
mgmtProto "github.com/netbirdio/netbird/management/proto"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
"github.com/netbirdio/netbird/management/server/settings"
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
@@ -189,6 +190,8 @@ func startServer(
|
|||||||
false,
|
false,
|
||||||
server.MocIntegratedValidator{},
|
server.MocIntegratedValidator{},
|
||||||
metrics,
|
metrics,
|
||||||
|
port_forwarding.NewControllerMock(),
|
||||||
|
settings.NewManagerMock(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed creating an account manager: %v", err)
|
t.Fatalf("failed creating an account manager: %v", err)
|
||||||
@@ -199,7 +202,7 @@ func startServer(
|
|||||||
context.Background(),
|
context.Background(),
|
||||||
config,
|
config,
|
||||||
accountManager,
|
accountManager,
|
||||||
settings.NewManager(str),
|
settings.NewManagerMock(),
|
||||||
peersUpdateManager,
|
peersUpdateManager,
|
||||||
secretsManager,
|
secretsManager,
|
||||||
nil,
|
nil,
|
||||||
|
|||||||
@@ -11,17 +11,18 @@ import (
|
|||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/domain"
|
"github.com/netbirdio/netbird/management/domain"
|
||||||
"github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||||
"github.com/netbirdio/netbird/management/server/idp"
|
"github.com/netbirdio/netbird/management/server/idp"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
"github.com/netbirdio/netbird/management/server/posture"
|
"github.com/netbirdio/netbird/management/server/posture"
|
||||||
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
"github.com/netbirdio/netbird/route"
|
"github.com/netbirdio/netbird/route"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ server.AccountManager = (*MockAccountManager)(nil)
|
var _ account.AccountManager = (*MockAccountManager)(nil)
|
||||||
|
|
||||||
type MockAccountManager struct {
|
type MockAccountManager struct {
|
||||||
GetOrCreateAccountByUserFunc func(ctx context.Context, userId, domain string) (*types.Account, error)
|
GetOrCreateAccountByUserFunc func(ctx context.Context, userId, domain string) (*types.Account, error)
|
||||||
@@ -33,7 +34,7 @@ type MockAccountManager struct {
|
|||||||
GetAccountIDByUserIdFunc func(ctx context.Context, userId, domain string) (string, error)
|
GetAccountIDByUserIdFunc func(ctx context.Context, userId, domain string) (string, error)
|
||||||
GetUserFromUserAuthFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
GetUserFromUserAuthFunc func(ctx context.Context, userAuth nbcontext.UserAuth) (*types.User, error)
|
||||||
ListUsersFunc func(ctx context.Context, accountID string) ([]*types.User, error)
|
ListUsersFunc func(ctx context.Context, accountID string) ([]*types.User, error)
|
||||||
GetPeersFunc func(ctx context.Context, accountID, userID string) ([]*nbpeer.Peer, error)
|
GetPeersFunc func(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error)
|
||||||
MarkPeerConnectedFunc func(ctx context.Context, peerKey string, connected bool, realIP net.IP) error
|
MarkPeerConnectedFunc func(ctx context.Context, peerKey string, connected bool, realIP net.IP) error
|
||||||
SyncAndMarkPeerFunc func(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
SyncAndMarkPeerFunc func(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
||||||
DeletePeerFunc func(ctx context.Context, accountID, peerKey, userID string) error
|
DeletePeerFunc func(ctx context.Context, accountID, peerKey, userID string) error
|
||||||
@@ -89,12 +90,12 @@ type MockAccountManager struct {
|
|||||||
SaveDNSSettingsFunc func(ctx context.Context, accountID, userID string, dnsSettingsToSave *types.DNSSettings) error
|
SaveDNSSettingsFunc func(ctx context.Context, accountID, userID string, dnsSettingsToSave *types.DNSSettings) error
|
||||||
GetPeerFunc func(ctx context.Context, accountID, peerID, userID string) (*nbpeer.Peer, error)
|
GetPeerFunc func(ctx context.Context, accountID, peerID, userID string) (*nbpeer.Peer, error)
|
||||||
UpdateAccountSettingsFunc func(ctx context.Context, accountID, userID string, newSettings *types.Settings) (*types.Account, error)
|
UpdateAccountSettingsFunc func(ctx context.Context, accountID, userID string, newSettings *types.Settings) (*types.Account, error)
|
||||||
LoginPeerFunc func(ctx context.Context, login server.PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
LoginPeerFunc func(ctx context.Context, login account.PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
||||||
SyncPeerFunc func(ctx context.Context, sync server.PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
SyncPeerFunc func(ctx context.Context, sync account.PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error)
|
||||||
InviteUserFunc func(ctx context.Context, accountID string, initiatorUserID string, targetUserEmail string) error
|
InviteUserFunc func(ctx context.Context, accountID string, initiatorUserID string, targetUserEmail string) error
|
||||||
GetAllConnectedPeersFunc func() (map[string]struct{}, error)
|
GetAllConnectedPeersFunc func() (map[string]struct{}, error)
|
||||||
HasConnectedChannelFunc func(peerID string) bool
|
HasConnectedChannelFunc func(peerID string) bool
|
||||||
GetExternalCacheManagerFunc func() server.ExternalCacheManager
|
GetExternalCacheManagerFunc func() account.ExternalCacheManager
|
||||||
GetPostureChecksFunc func(ctx context.Context, accountID, postureChecksID, userID string) (*posture.Checks, error)
|
GetPostureChecksFunc func(ctx context.Context, accountID, postureChecksID, userID string) (*posture.Checks, error)
|
||||||
SavePostureChecksFunc func(ctx context.Context, accountID, userID string, postureChecks *posture.Checks) (*posture.Checks, error)
|
SavePostureChecksFunc func(ctx context.Context, accountID, userID string, postureChecks *posture.Checks) (*posture.Checks, error)
|
||||||
DeletePostureChecksFunc func(ctx context.Context, accountID, postureChecksID, userID string) error
|
DeletePostureChecksFunc func(ctx context.Context, accountID, postureChecksID, userID string) error
|
||||||
@@ -110,6 +111,7 @@ type MockAccountManager struct {
|
|||||||
GetAccountSettingsFunc func(ctx context.Context, accountID string, userID string) (*types.Settings, error)
|
GetAccountSettingsFunc func(ctx context.Context, accountID string, userID string) (*types.Settings, error)
|
||||||
DeleteSetupKeyFunc func(ctx context.Context, accountID, userID, keyID string) error
|
DeleteSetupKeyFunc func(ctx context.Context, accountID, userID, keyID string) error
|
||||||
BuildUserInfosForAccountFunc func(ctx context.Context, accountID, initiatorUserID string, accountUsers []*types.User) (map[string]*types.UserInfo, error)
|
BuildUserInfosForAccountFunc func(ctx context.Context, accountID, initiatorUserID string, accountUsers []*types.User) (map[string]*types.UserInfo, error)
|
||||||
|
GetStoreFunc func() store.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
func (am *MockAccountManager) UpdateAccountPeers(ctx context.Context, accountID string) {
|
func (am *MockAccountManager) UpdateAccountPeers(ctx context.Context, accountID string) {
|
||||||
@@ -605,9 +607,9 @@ func (am *MockAccountManager) GetAccountIDFromUserAuth(ctx context.Context, user
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPeers mocks GetPeers of the AccountManager interface
|
// GetPeers mocks GetPeers of the AccountManager interface
|
||||||
func (am *MockAccountManager) GetPeers(ctx context.Context, accountID, userID string) ([]*nbpeer.Peer, error) {
|
func (am *MockAccountManager) GetPeers(ctx context.Context, accountID, userID, nameFilter, ipFilter string) ([]*nbpeer.Peer, error) {
|
||||||
if am.GetPeersFunc != nil {
|
if am.GetPeersFunc != nil {
|
||||||
return am.GetPeersFunc(ctx, accountID, userID)
|
return am.GetPeersFunc(ctx, accountID, userID, nameFilter, ipFilter)
|
||||||
}
|
}
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetPeers is not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetPeers is not implemented")
|
||||||
}
|
}
|
||||||
@@ -661,7 +663,7 @@ func (am *MockAccountManager) UpdateAccountSettings(ctx context.Context, account
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoginPeer mocks LoginPeer of the AccountManager interface
|
// LoginPeer mocks LoginPeer of the AccountManager interface
|
||||||
func (am *MockAccountManager) LoginPeer(ctx context.Context, login server.PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
func (am *MockAccountManager) LoginPeer(ctx context.Context, login account.PeerLogin) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
||||||
if am.LoginPeerFunc != nil {
|
if am.LoginPeerFunc != nil {
|
||||||
return am.LoginPeerFunc(ctx, login)
|
return am.LoginPeerFunc(ctx, login)
|
||||||
}
|
}
|
||||||
@@ -669,7 +671,7 @@ func (am *MockAccountManager) LoginPeer(ctx context.Context, login server.PeerLo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SyncPeer mocks SyncPeer of the AccountManager interface
|
// SyncPeer mocks SyncPeer of the AccountManager interface
|
||||||
func (am *MockAccountManager) SyncPeer(ctx context.Context, sync server.PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
func (am *MockAccountManager) SyncPeer(ctx context.Context, sync account.PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
||||||
if am.SyncPeerFunc != nil {
|
if am.SyncPeerFunc != nil {
|
||||||
return am.SyncPeerFunc(ctx, sync, accountID)
|
return am.SyncPeerFunc(ctx, sync, accountID)
|
||||||
}
|
}
|
||||||
@@ -700,7 +702,7 @@ func (am *MockAccountManager) StoreEvent(ctx context.Context, initiatorID, targe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetExternalCacheManager mocks GetExternalCacheManager of the AccountManager interface
|
// GetExternalCacheManager mocks GetExternalCacheManager of the AccountManager interface
|
||||||
func (am *MockAccountManager) GetExternalCacheManager() server.ExternalCacheManager {
|
func (am *MockAccountManager) GetExternalCacheManager() account.ExternalCacheManager {
|
||||||
if am.GetExternalCacheManagerFunc() != nil {
|
if am.GetExternalCacheManagerFunc() != nil {
|
||||||
return am.GetExternalCacheManagerFunc()
|
return am.GetExternalCacheManagerFunc()
|
||||||
}
|
}
|
||||||
@@ -838,3 +840,10 @@ func (am *MockAccountManager) BuildUserInfosForAccount(ctx context.Context, acco
|
|||||||
func (am *MockAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
func (am *MockAccountManager) SyncUserJWTGroups(ctx context.Context, userAuth nbcontext.UserAuth) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method SyncUserJWTGroups is not implemented")
|
return status.Errorf(codes.Unimplemented, "method SyncUserJWTGroups is not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (am *MockAccountManager) GetStore() store.Store {
|
||||||
|
if am.GetStoreFunc != nil {
|
||||||
|
return am.GetStoreFunc()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import (
|
|||||||
|
|
||||||
nbdns "github.com/netbirdio/netbird/dns"
|
nbdns "github.com/netbirdio/netbird/dns"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
|
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||||
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
nbpeer "github.com/netbirdio/netbird/management/server/peer"
|
||||||
|
"github.com/netbirdio/netbird/management/server/settings"
|
||||||
"github.com/netbirdio/netbird/management/server/store"
|
"github.com/netbirdio/netbird/management/server/store"
|
||||||
"github.com/netbirdio/netbird/management/server/telemetry"
|
"github.com/netbirdio/netbird/management/server/telemetry"
|
||||||
"github.com/netbirdio/netbird/management/server/types"
|
"github.com/netbirdio/netbird/management/server/types"
|
||||||
@@ -771,7 +773,7 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
metrics, err := telemetry.NewDefaultAppMetrics(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics)
|
return BuildManager(context.Background(), store, NewPeersUpdateManager(nil), nil, "", "netbird.selfhosted", eventStore, nil, false, MocIntegratedValidator{}, metrics, port_forwarding.NewControllerMock(), settings.NewManagerMock())
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNSStore(t *testing.T) (store.Store, error) {
|
func createNSStore(t *testing.T) (store.Store, error) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/resources"
|
"github.com/netbirdio/netbird/management/server/networks/resources"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/routers"
|
"github.com/netbirdio/netbird/management/server/networks/routers"
|
||||||
@@ -26,7 +26,7 @@ type Manager interface {
|
|||||||
|
|
||||||
type managerImpl struct {
|
type managerImpl struct {
|
||||||
store store.Store
|
store store.Store
|
||||||
accountManager s.AccountManager
|
accountManager account.AccountManager
|
||||||
permissionsManager permissions.Manager
|
permissionsManager permissions.Manager
|
||||||
resourcesManager resources.Manager
|
resourcesManager resources.Manager
|
||||||
routersManager routers.Manager
|
routersManager routers.Manager
|
||||||
@@ -35,7 +35,7 @@ type managerImpl struct {
|
|||||||
type mockManager struct {
|
type mockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(store store.Store, permissionsManager permissions.Manager, resourceManager resources.Manager, routersManager routers.Manager, accountManager s.AccountManager) Manager {
|
func NewManager(store store.Store, permissionsManager permissions.Manager, resourceManager resources.Manager, routersManager routers.Manager, accountManager account.AccountManager) Manager {
|
||||||
return &managerImpl{
|
return &managerImpl{
|
||||||
store: store,
|
store: store,
|
||||||
permissionsManager: permissionsManager,
|
permissionsManager: permissionsManager,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/groups"
|
"github.com/netbirdio/netbird/management/server/groups"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
"github.com/netbirdio/netbird/management/server/networks/resources/types"
|
||||||
@@ -31,13 +31,13 @@ type managerImpl struct {
|
|||||||
store store.Store
|
store store.Store
|
||||||
permissionsManager permissions.Manager
|
permissionsManager permissions.Manager
|
||||||
groupsManager groups.Manager
|
groupsManager groups.Manager
|
||||||
accountManager s.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockManager struct {
|
type mockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(store store.Store, permissionsManager permissions.Manager, groupsManager groups.Manager, accountManager s.AccountManager) Manager {
|
func NewManager(store store.Store, permissionsManager permissions.Manager, groupsManager groups.Manager, accountManager account.AccountManager) Manager {
|
||||||
return &managerImpl{
|
return &managerImpl{
|
||||||
store: store,
|
store: store,
|
||||||
permissionsManager: permissionsManager,
|
permissionsManager: permissionsManager,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rs/xid"
|
"github.com/rs/xid"
|
||||||
|
|
||||||
s "github.com/netbirdio/netbird/management/server"
|
"github.com/netbirdio/netbird/management/server/account"
|
||||||
"github.com/netbirdio/netbird/management/server/activity"
|
"github.com/netbirdio/netbird/management/server/activity"
|
||||||
"github.com/netbirdio/netbird/management/server/networks/routers/types"
|
"github.com/netbirdio/netbird/management/server/networks/routers/types"
|
||||||
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
|
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
|
||||||
@@ -29,13 +29,13 @@ type Manager interface {
|
|||||||
type managerImpl struct {
|
type managerImpl struct {
|
||||||
store store.Store
|
store store.Store
|
||||||
permissionsManager permissions.Manager
|
permissionsManager permissions.Manager
|
||||||
accountManager s.AccountManager
|
accountManager account.AccountManager
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockManager struct {
|
type mockManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager s.AccountManager) Manager {
|
func NewManager(store store.Store, permissionsManager permissions.Manager, accountManager account.AccountManager) Manager {
|
||||||
return &managerImpl{
|
return &managerImpl{
|
||||||
store: store,
|
store: store,
|
||||||
permissionsManager: permissionsManager,
|
permissionsManager: permissionsManager,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user