mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-21 01:36:46 +00:00
Compare commits
12 Commits
v0.32.0
...
debug-0.33
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3efa7a282a | ||
|
|
40551099b3 | ||
|
|
9db1932664 | ||
|
|
1bbabf70b0 | ||
|
|
aa575d6f44 | ||
|
|
f66bbcc54c | ||
|
|
5dd6a08ea6 | ||
|
|
eb5d0569ae | ||
|
|
52ea2e84e9 | ||
|
|
78fab877c0 | ||
|
|
65a94f695f | ||
|
|
ec543f89fb |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -9,7 +9,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
SIGN_PIPE_VER: "v0.0.16"
|
SIGN_PIPE_VER: "v0.0.17"
|
||||||
GORELEASER_VER: "v2.3.2"
|
GORELEASER_VER: "v2.3.2"
|
||||||
PRODUCT_NAME: "NetBird"
|
PRODUCT_NAME: "NetBird"
|
||||||
COPYRIGHT: "Wiretrustee UG (haftungsbeschreankt)"
|
COPYRIGHT: "Wiretrustee UG (haftungsbeschreankt)"
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
<br>
|
<br>
|
||||||
<a href="https://join.slack.com/t/netbirdio/shared_invite/zt-2p5zwhm4g-8fHollzrQa5y4PZF5AEpvQ">
|
<a href="https://join.slack.com/t/netbirdio/shared_invite/zt-2p5zwhm4g-8fHollzrQa5y4PZF5AEpvQ">
|
||||||
<img src="https://img.shields.io/badge/slack-@netbird-red.svg?logo=slack"/>
|
<img src="https://img.shields.io/badge/slack-@netbird-red.svg?logo=slack"/>
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a href="https://gurubase.io/g/netbird">
|
||||||
|
<img src="https://img.shields.io/badge/Gurubase-Ask%20NetBird%20Guru-006BFF"/>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ func (m *Manager) AllowNetbird() error {
|
|||||||
|
|
||||||
var chain *nftables.Chain
|
var chain *nftables.Chain
|
||||||
for _, c := range chains {
|
for _, c := range chains {
|
||||||
if c.Table.Name == tableNameFilter && c.Name == chainNameForward {
|
if c.Table.Name == tableNameFilter && c.Name == chainNameInput {
|
||||||
chain = c
|
chain = c
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -276,7 +276,7 @@ func (m *Manager) resetNetbirdInputRules() error {
|
|||||||
|
|
||||||
func (m *Manager) deleteNetbirdInputRules(chains []*nftables.Chain) {
|
func (m *Manager) deleteNetbirdInputRules(chains []*nftables.Chain) {
|
||||||
for _, c := range chains {
|
for _, c := range chains {
|
||||||
if c.Table.Name == "filter" && c.Name == "INPUT" {
|
if c.Table.Name == tableNameFilter && c.Name == chainNameInput {
|
||||||
rules, err := m.rConn.GetRules(c.Table, c)
|
rules, err := m.rConn.GetRules(c.Table, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("get rules for chain %q: %v", c.Name, err)
|
log.Errorf("get rules for chain %q: %v", c.Name, err)
|
||||||
@@ -351,7 +351,9 @@ func (m *Manager) applyAllowNetbirdRules(chain *nftables.Chain) {
|
|||||||
Register: 1,
|
Register: 1,
|
||||||
Data: ifname(m.wgIface.Name()),
|
Data: ifname(m.wgIface.Name()),
|
||||||
},
|
},
|
||||||
&expr.Verdict{},
|
&expr.Verdict{
|
||||||
|
Kind: expr.VerdictAccept,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
UserData: []byte(allowNetbirdInputRuleID),
|
UserData: []byte(allowNetbirdInputRuleID),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ func TestDNSPermanent_matchOnly(t *testing.T) {
|
|||||||
Port: 53,
|
Port: 53,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Domains: []string{"customdomain.com"},
|
Domains: []string{"google.com"},
|
||||||
Primary: false,
|
Primary: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -804,7 +804,7 @@ func TestDNSPermanent_matchOnly(t *testing.T) {
|
|||||||
if ips[0] != zoneRecords[0].RData {
|
if ips[0] != zoneRecords[0].RData {
|
||||||
t.Fatalf("invalid zone record: %v", err)
|
t.Fatalf("invalid zone record: %v", err)
|
||||||
}
|
}
|
||||||
_, err = resolver.LookupHost(context.Background(), "customdomain.com")
|
_, err = resolver.LookupHost(context.Background(), "google.com")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("failed to resolve: %s", err)
|
t.Errorf("failed to resolve: %s", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ type ruleParams struct {
|
|||||||
|
|
||||||
// isLegacy determines whether to use the legacy routing setup
|
// isLegacy determines whether to use the legacy routing setup
|
||||||
func isLegacy() bool {
|
func isLegacy() bool {
|
||||||
return os.Getenv("NB_USE_LEGACY_ROUTING") == "true" || nbnet.CustomRoutingDisabled()
|
return os.Getenv("NB_USE_LEGACY_ROUTING") == "true" || nbnet.CustomRoutingDisabled() || os.Getenv(nbnet.EnvSkipSocketMark) == "true"
|
||||||
}
|
}
|
||||||
|
|
||||||
// setIsLegacy sets the legacy routing setup
|
// setIsLegacy sets the legacy routing setup
|
||||||
|
|||||||
@@ -1,13 +1,41 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/netbirdio/netbird/client/cmd"
|
"github.com/netbirdio/netbird/client/cmd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// only if env is not set
|
||||||
|
if os.Getenv("NB_LOG_LEVEL") == "" {
|
||||||
|
if err := os.Setenv("NB_LOG_LEVEL", "debug"); err != nil {
|
||||||
|
log.Errorf("Failed setting log-level: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := os.Setenv("NB_LOG_MAX_SIZE_MB", "100"); err != nil {
|
||||||
|
log.Errorf("Failed setting log-size: %v", err)
|
||||||
|
}
|
||||||
|
if err := os.Setenv("NB_WINDOWS_PANIC_LOG", filepath.Join(os.Getenv("ProgramData"), "netbird", "netbird.err")); err != nil {
|
||||||
|
log.Errorf("Failed setting panic log path: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go startPprofServer()
|
||||||
|
|
||||||
if err := cmd.Execute(); err != nil {
|
if err := cmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startPprofServer() {
|
||||||
|
pprofAddr := "localhost:6969"
|
||||||
|
log.Infof("Starting pprof debugging server on %s", pprofAddr)
|
||||||
|
if err := http.ListenAndServe(pprofAddr, nil); err != nil {
|
||||||
|
log.Infof("pprof server failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -120,6 +120,35 @@ func (s *Server) Start() error {
|
|||||||
ctx, cancel := context.WithCancel(s.rootCtx)
|
ctx, cancel := context.WithCancel(s.rootCtx)
|
||||||
s.actCancel = cancel
|
s.actCancel = cancel
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
ticker := time.NewTicker(30 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
if statusResp, err := s.Status(ctx, &proto.StatusRequest{GetFullPeerStatus: true}); err != nil {
|
||||||
|
log.Infof("Error getting status: %v", err)
|
||||||
|
} else if statusResp.FullStatus != nil {
|
||||||
|
log.Infof("Status --------")
|
||||||
|
for _, peer := range statusResp.FullStatus.Peers {
|
||||||
|
log.Infof("[Peer Connection] Name: %s, IP: %s, Key: %s, Connection Status: %s, Relayed: %v, RelayedAddress: %v, Last WireGuard Handshake: %v",
|
||||||
|
peer.Fqdn,
|
||||||
|
peer.IP,
|
||||||
|
peer.PubKey,
|
||||||
|
peer.ConnStatus,
|
||||||
|
peer.Relayed,
|
||||||
|
peer.RelayAddress,
|
||||||
|
peer.LastWireguardHandshake.AsTime().Format("15:04:05"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// if configuration exists, we just start connections. if is new config we skip and set status NeedsLogin
|
// if configuration exists, we just start connections. if is new config we skip and set status NeedsLogin
|
||||||
// on failure we return error to retry
|
// on failure we return error to retry
|
||||||
config, err := internal.UpdateConfig(s.latestConfigInput)
|
config, err := internal.UpdateConfig(s.latestConfigInput)
|
||||||
|
|||||||
@@ -965,7 +965,9 @@ func (am *DefaultAccountManager) getJWTGroupsChanges(user *User, groups []*nbgro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UserGroupsAddToPeers adds groups to all peers of user
|
// UserGroupsAddToPeers adds groups to all peers of user
|
||||||
func (a *Account) UserGroupsAddToPeers(userID string, groups ...string) {
|
func (a *Account) UserGroupsAddToPeers(userID string, groups ...string) map[string][]string {
|
||||||
|
groupUpdates := make(map[string][]string)
|
||||||
|
|
||||||
userPeers := make(map[string]struct{})
|
userPeers := make(map[string]struct{})
|
||||||
for pid, peer := range a.Peers {
|
for pid, peer := range a.Peers {
|
||||||
if peer.UserID == userID {
|
if peer.UserID == userID {
|
||||||
@@ -979,6 +981,8 @@ func (a *Account) UserGroupsAddToPeers(userID string, groups ...string) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldPeers := group.Peers
|
||||||
|
|
||||||
groupPeers := make(map[string]struct{})
|
groupPeers := make(map[string]struct{})
|
||||||
for _, pid := range group.Peers {
|
for _, pid := range group.Peers {
|
||||||
groupPeers[pid] = struct{}{}
|
groupPeers[pid] = struct{}{}
|
||||||
@@ -992,16 +996,25 @@ func (a *Account) UserGroupsAddToPeers(userID string, groups ...string) {
|
|||||||
for pid := range groupPeers {
|
for pid := range groupPeers {
|
||||||
group.Peers = append(group.Peers, pid)
|
group.Peers = append(group.Peers, pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
groupUpdates[gid] = difference(group.Peers, oldPeers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return groupUpdates
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserGroupsRemoveFromPeers removes groups from all peers of user
|
// UserGroupsRemoveFromPeers removes groups from all peers of user
|
||||||
func (a *Account) UserGroupsRemoveFromPeers(userID string, groups ...string) {
|
func (a *Account) UserGroupsRemoveFromPeers(userID string, groups ...string) map[string][]string {
|
||||||
|
groupUpdates := make(map[string][]string)
|
||||||
|
|
||||||
for _, gid := range groups {
|
for _, gid := range groups {
|
||||||
group, ok := a.Groups[gid]
|
group, ok := a.Groups[gid]
|
||||||
if !ok || group.Name == "All" {
|
if !ok || group.Name == "All" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oldPeers := group.Peers
|
||||||
|
|
||||||
update := make([]string, 0, len(group.Peers))
|
update := make([]string, 0, len(group.Peers))
|
||||||
for _, pid := range group.Peers {
|
for _, pid := range group.Peers {
|
||||||
peer, ok := a.Peers[pid]
|
peer, ok := a.Peers[pid]
|
||||||
@@ -1013,7 +1026,10 @@ func (a *Account) UserGroupsRemoveFromPeers(userID string, groups ...string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
group.Peers = update
|
group.Peers = update
|
||||||
|
groupUpdates[gid] = difference(oldPeers, group.Peers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return groupUpdates
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildManager creates a new DefaultAccountManager with a provided Store
|
// BuildManager creates a new DefaultAccountManager with a provided Store
|
||||||
@@ -1175,6 +1191,11 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = am.handleGroupsPropagationSettings(ctx, oldSettings, newSettings, userID, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("groups propagation failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
updatedAccount := account.UpdateSettings(newSettings)
|
updatedAccount := account.UpdateSettings(newSettings)
|
||||||
|
|
||||||
err = am.Store.SaveAccount(ctx, account)
|
err = am.Store.SaveAccount(ctx, account)
|
||||||
@@ -1185,6 +1206,19 @@ func (am *DefaultAccountManager) UpdateAccountSettings(ctx context.Context, acco
|
|||||||
return updatedAccount, nil
|
return updatedAccount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (am *DefaultAccountManager) handleGroupsPropagationSettings(ctx context.Context, oldSettings, newSettings *Settings, userID, accountID string) error {
|
||||||
|
if oldSettings.GroupsPropagationEnabled != newSettings.GroupsPropagationEnabled {
|
||||||
|
if newSettings.GroupsPropagationEnabled {
|
||||||
|
am.StoreEvent(ctx, userID, accountID, accountID, activity.UserGroupPropagationEnabled, nil)
|
||||||
|
// Todo: retroactively add user groups to all peers
|
||||||
|
} else {
|
||||||
|
am.StoreEvent(ctx, userID, accountID, accountID, activity.UserGroupPropagationDisabled, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (am *DefaultAccountManager) handleInactivityExpirationSettings(ctx context.Context, account *Account, oldSettings, newSettings *Settings, userID, accountID string) error {
|
func (am *DefaultAccountManager) handleInactivityExpirationSettings(ctx context.Context, account *Account, oldSettings, newSettings *Settings, userID, accountID string) error {
|
||||||
|
|
||||||
if newSettings.PeerInactivityExpirationEnabled {
|
if newSettings.PeerInactivityExpirationEnabled {
|
||||||
|
|||||||
@@ -148,6 +148,9 @@ const (
|
|||||||
AccountPeerInactivityExpirationDurationUpdated Activity = 67
|
AccountPeerInactivityExpirationDurationUpdated Activity = 67
|
||||||
|
|
||||||
SetupKeyDeleted Activity = 68
|
SetupKeyDeleted Activity = 68
|
||||||
|
|
||||||
|
UserGroupPropagationEnabled Activity = 69
|
||||||
|
UserGroupPropagationDisabled Activity = 70
|
||||||
)
|
)
|
||||||
|
|
||||||
var activityMap = map[Activity]Code{
|
var activityMap = map[Activity]Code{
|
||||||
@@ -222,6 +225,9 @@ var activityMap = map[Activity]Code{
|
|||||||
AccountPeerInactivityExpirationDisabled: {"Account peer inactivity expiration disabled", "account.peer.inactivity.expiration.disable"},
|
AccountPeerInactivityExpirationDisabled: {"Account peer inactivity expiration disabled", "account.peer.inactivity.expiration.disable"},
|
||||||
AccountPeerInactivityExpirationDurationUpdated: {"Account peer inactivity expiration duration updated", "account.peer.inactivity.expiration.update"},
|
AccountPeerInactivityExpirationDurationUpdated: {"Account peer inactivity expiration duration updated", "account.peer.inactivity.expiration.update"},
|
||||||
SetupKeyDeleted: {"Setup key deleted", "setupkey.delete"},
|
SetupKeyDeleted: {"Setup key deleted", "setupkey.delete"},
|
||||||
|
|
||||||
|
UserGroupPropagationEnabled: {"User group propagation enabled", "account.setting.group.propagation.enable"},
|
||||||
|
UserGroupPropagationDisabled: {"User group propagation disabled", "account.setting.group.propagation.disable"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringCode returns a string code of the activity
|
// StringCode returns a string code of the activity
|
||||||
|
|||||||
@@ -439,17 +439,13 @@ components:
|
|||||||
example: 5
|
example: 5
|
||||||
required:
|
required:
|
||||||
- accessible_peers_count
|
- accessible_peers_count
|
||||||
SetupKey:
|
SetupKeyBase:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
description: Setup Key ID
|
description: Setup Key ID
|
||||||
type: string
|
type: string
|
||||||
example: 2531583362
|
example: 2531583362
|
||||||
key:
|
|
||||||
description: Setup Key value
|
|
||||||
type: string
|
|
||||||
example: A616097E-FCF0-48FA-9354-CA4A61142761
|
|
||||||
name:
|
name:
|
||||||
description: Setup key name identifier
|
description: Setup key name identifier
|
||||||
type: string
|
type: string
|
||||||
@@ -518,6 +514,28 @@ components:
|
|||||||
- updated_at
|
- updated_at
|
||||||
- usage_limit
|
- usage_limit
|
||||||
- ephemeral
|
- ephemeral
|
||||||
|
SetupKeyClear:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/SetupKeyBase'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: Setup Key as plain text
|
||||||
|
type: string
|
||||||
|
example: A616097E-FCF0-48FA-9354-CA4A61142761
|
||||||
|
required:
|
||||||
|
- key
|
||||||
|
SetupKey:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/SetupKeyBase'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
key:
|
||||||
|
description: Setup Key as secret
|
||||||
|
type: string
|
||||||
|
example: A6160****
|
||||||
|
required:
|
||||||
|
- key
|
||||||
SetupKeyRequest:
|
SetupKeyRequest:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1918,7 +1936,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/SetupKey'
|
$ref: '#/components/schemas/SetupKeyClear'
|
||||||
'400':
|
'400':
|
||||||
"$ref": "#/components/responses/bad_request"
|
"$ref": "#/components/responses/bad_request"
|
||||||
'401':
|
'401':
|
||||||
|
|||||||
@@ -1062,7 +1062,94 @@ type SetupKey struct {
|
|||||||
// Id Setup Key ID
|
// Id Setup Key ID
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
|
|
||||||
// Key Setup Key value
|
// Key Setup Key as secret
|
||||||
|
Key string `json:"key"`
|
||||||
|
|
||||||
|
// LastUsed Setup key last usage date
|
||||||
|
LastUsed time.Time `json:"last_used"`
|
||||||
|
|
||||||
|
// Name Setup key name identifier
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Revoked Setup key revocation status
|
||||||
|
Revoked bool `json:"revoked"`
|
||||||
|
|
||||||
|
// State Setup key status, "valid", "overused","expired" or "revoked"
|
||||||
|
State string `json:"state"`
|
||||||
|
|
||||||
|
// Type Setup key type, one-off for single time usage and reusable
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// UpdatedAt Setup key last update date
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// UsageLimit A number of times this key can be used. The value of 0 indicates the unlimited usage.
|
||||||
|
UsageLimit int `json:"usage_limit"`
|
||||||
|
|
||||||
|
// UsedTimes Usage count of setup key
|
||||||
|
UsedTimes int `json:"used_times"`
|
||||||
|
|
||||||
|
// Valid Setup key validity status
|
||||||
|
Valid bool `json:"valid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupKeyBase defines model for SetupKeyBase.
|
||||||
|
type SetupKeyBase struct {
|
||||||
|
// AutoGroups List of group IDs to auto-assign to peers registered with this key
|
||||||
|
AutoGroups []string `json:"auto_groups"`
|
||||||
|
|
||||||
|
// Ephemeral Indicate that the peer will be ephemeral or not
|
||||||
|
Ephemeral bool `json:"ephemeral"`
|
||||||
|
|
||||||
|
// Expires Setup Key expiration date
|
||||||
|
Expires time.Time `json:"expires"`
|
||||||
|
|
||||||
|
// Id Setup Key ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// LastUsed Setup key last usage date
|
||||||
|
LastUsed time.Time `json:"last_used"`
|
||||||
|
|
||||||
|
// Name Setup key name identifier
|
||||||
|
Name string `json:"name"`
|
||||||
|
|
||||||
|
// Revoked Setup key revocation status
|
||||||
|
Revoked bool `json:"revoked"`
|
||||||
|
|
||||||
|
// State Setup key status, "valid", "overused","expired" or "revoked"
|
||||||
|
State string `json:"state"`
|
||||||
|
|
||||||
|
// Type Setup key type, one-off for single time usage and reusable
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// UpdatedAt Setup key last update date
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
// UsageLimit A number of times this key can be used. The value of 0 indicates the unlimited usage.
|
||||||
|
UsageLimit int `json:"usage_limit"`
|
||||||
|
|
||||||
|
// UsedTimes Usage count of setup key
|
||||||
|
UsedTimes int `json:"used_times"`
|
||||||
|
|
||||||
|
// Valid Setup key validity status
|
||||||
|
Valid bool `json:"valid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupKeyClear defines model for SetupKeyClear.
|
||||||
|
type SetupKeyClear struct {
|
||||||
|
// AutoGroups List of group IDs to auto-assign to peers registered with this key
|
||||||
|
AutoGroups []string `json:"auto_groups"`
|
||||||
|
|
||||||
|
// Ephemeral Indicate that the peer will be ephemeral or not
|
||||||
|
Ephemeral bool `json:"ephemeral"`
|
||||||
|
|
||||||
|
// Expires Setup Key expiration date
|
||||||
|
Expires time.Time `json:"expires"`
|
||||||
|
|
||||||
|
// Id Setup Key ID
|
||||||
|
Id string `json:"id"`
|
||||||
|
|
||||||
|
// Key Setup Key as plain text
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
|
||||||
// LastUsed Setup key last usage date
|
// LastUsed Setup key last usage date
|
||||||
|
|||||||
@@ -667,6 +667,8 @@ func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, ac
|
|||||||
|
|
||||||
updated := peer.UpdateMetaIfNew(sync.Meta)
|
updated := peer.UpdateMetaIfNew(sync.Meta)
|
||||||
if updated {
|
if updated {
|
||||||
|
am.metrics.AccountManagerMetrics().CountPeerMetUpdate()
|
||||||
|
account.Peers[peer.ID] = peer
|
||||||
log.WithContext(ctx).Tracef("peer %s metadata updated", peer.ID)
|
log.WithContext(ctx).Tracef("peer %s metadata updated", peer.ID)
|
||||||
err = am.Store.SavePeer(ctx, account.Id, peer)
|
err = am.Store.SavePeer(ctx, account.Id, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -800,6 +802,7 @@ func (am *DefaultAccountManager) LoginPeer(ctx context.Context, login PeerLogin)
|
|||||||
|
|
||||||
updated := peer.UpdateMetaIfNew(login.Meta)
|
updated := peer.UpdateMetaIfNew(login.Meta)
|
||||||
if updated {
|
if updated {
|
||||||
|
am.metrics.AccountManagerMetrics().CountPeerMetUpdate()
|
||||||
shouldStorePeer = true
|
shouldStorePeer = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,6 +991,12 @@ func (am *DefaultAccountManager) GetPeer(ctx context.Context, accountID, peerID,
|
|||||||
// updateAccountPeers updates all peers that belong to an account.
|
// updateAccountPeers updates all peers that belong to an account.
|
||||||
// Should be called when changes have to be synced to peers.
|
// Should be called when changes have to be synced to peers.
|
||||||
func (am *DefaultAccountManager) updateAccountPeers(ctx context.Context, accountID string) {
|
func (am *DefaultAccountManager) updateAccountPeers(ctx context.Context, accountID string) {
|
||||||
|
account, err := am.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
log.WithContext(ctx).Errorf("failed to send out updates to peers: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
if am.metrics != nil {
|
if am.metrics != nil {
|
||||||
@@ -995,11 +1004,6 @@ func (am *DefaultAccountManager) updateAccountPeers(ctx context.Context, account
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
account, err := am.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
|
||||||
if err != nil {
|
|
||||||
log.WithContext(ctx).Errorf("failed to send out updates to peers: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
peers := account.GetPeers()
|
peers := account.GetPeers()
|
||||||
|
|
||||||
approvedPeersMap, err := am.GetValidatedPeers(account)
|
approvedPeersMap, err := am.GetValidatedPeers(account)
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ func (am *DefaultAccountManager) GetSetupKey(ctx context.Context, accountID, use
|
|||||||
return nil, status.NewAdminPermissionError()
|
return nil, status.NewAdminPermissionError()
|
||||||
}
|
}
|
||||||
|
|
||||||
setupKey, err := am.Store.GetSetupKeyByID(ctx, LockingStrengthShare, keyID, accountID)
|
setupKey, err := am.Store.GetSetupKeyByID(ctx, LockingStrengthShare, accountID, keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,22 +210,41 @@ func TestGetSetupKeys(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = manager.SaveGroup(context.Background(), account.Id, userID, &nbgroup.Group{
|
plainKey, err := manager.CreateSetupKey(context.Background(), account.Id, "key1", SetupKeyReusable, time.Hour, nil, SetupKeyUnlimitedUsage, userID, false)
|
||||||
ID: "group_1",
|
|
||||||
Name: "group_name_1",
|
|
||||||
Peers: []string{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = manager.SaveGroup(context.Background(), account.Id, userID, &nbgroup.Group{
|
type testCase struct {
|
||||||
ID: "group_2",
|
name string
|
||||||
Name: "group_name_2",
|
keyId string
|
||||||
Peers: []string{},
|
expectedFailure bool
|
||||||
})
|
}
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
testCase1 := testCase{
|
||||||
|
name: "Should get existing Setup Key",
|
||||||
|
keyId: plainKey.Id,
|
||||||
|
expectedFailure: false,
|
||||||
|
}
|
||||||
|
testCase2 := testCase{
|
||||||
|
name: "Should fail to get non-existent Setup Key",
|
||||||
|
keyId: "some key",
|
||||||
|
expectedFailure: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tCase := range []testCase{testCase1, testCase2} {
|
||||||
|
t.Run(tCase.name, func(t *testing.T) {
|
||||||
|
key, err := manager.GetSetupKey(context.Background(), account.Id, userID, tCase.keyId)
|
||||||
|
|
||||||
|
if tCase.expectedFailure {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected to fail")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NotEqual(t, plainKey.Key, key.Key)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1123,6 +1123,7 @@ func (s *SqlStore) IncrementNetworkSerial(ctx context.Context, lockStrength Lock
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlStore) ExecuteInTransaction(ctx context.Context, operation func(store Store) error) error {
|
func (s *SqlStore) ExecuteInTransaction(ctx context.Context, operation func(store Store) error) error {
|
||||||
|
startTime := time.Now()
|
||||||
tx := s.db.Begin()
|
tx := s.db.Begin()
|
||||||
if tx.Error != nil {
|
if tx.Error != nil {
|
||||||
return tx.Error
|
return tx.Error
|
||||||
@@ -1133,7 +1134,15 @@ func (s *SqlStore) ExecuteInTransaction(ctx context.Context, operation func(stor
|
|||||||
tx.Rollback()
|
tx.Rollback()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return tx.Commit().Error
|
|
||||||
|
err = tx.Commit().Error
|
||||||
|
|
||||||
|
log.WithContext(ctx).Tracef("transaction took %v", time.Since(startTime))
|
||||||
|
if s.metrics != nil {
|
||||||
|
s.metrics.StoreMetrics().CountTransactionDuration(time.Since(startTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlStore) withTx(tx *gorm.DB) Store {
|
func (s *SqlStore) withTx(tx *gorm.DB) Store {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type AccountManagerMetrics struct {
|
|||||||
updateAccountPeersDurationMs metric.Float64Histogram
|
updateAccountPeersDurationMs metric.Float64Histogram
|
||||||
getPeerNetworkMapDurationMs metric.Float64Histogram
|
getPeerNetworkMapDurationMs metric.Float64Histogram
|
||||||
networkMapObjectCount metric.Int64Histogram
|
networkMapObjectCount metric.Int64Histogram
|
||||||
|
peerMetaUpdateCount metric.Int64Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAccountManagerMetrics creates an instance of AccountManagerMetrics
|
// NewAccountManagerMetrics creates an instance of AccountManagerMetrics
|
||||||
@@ -44,11 +45,17 @@ func NewAccountManagerMetrics(ctx context.Context, meter metric.Meter) (*Account
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerMetaUpdateCount, err := meter.Int64Counter("management.account.peer.meta.update.counter", metric.WithUnit("1"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &AccountManagerMetrics{
|
return &AccountManagerMetrics{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
getPeerNetworkMapDurationMs: getPeerNetworkMapDurationMs,
|
getPeerNetworkMapDurationMs: getPeerNetworkMapDurationMs,
|
||||||
updateAccountPeersDurationMs: updateAccountPeersDurationMs,
|
updateAccountPeersDurationMs: updateAccountPeersDurationMs,
|
||||||
networkMapObjectCount: networkMapObjectCount,
|
networkMapObjectCount: networkMapObjectCount,
|
||||||
|
peerMetaUpdateCount: peerMetaUpdateCount,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -67,3 +74,8 @@ func (metrics *AccountManagerMetrics) CountGetPeerNetworkMapDuration(duration ti
|
|||||||
func (metrics *AccountManagerMetrics) CountNetworkMapObjects(count int64) {
|
func (metrics *AccountManagerMetrics) CountNetworkMapObjects(count int64) {
|
||||||
metrics.networkMapObjectCount.Record(metrics.ctx, count)
|
metrics.networkMapObjectCount.Record(metrics.ctx, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountPeerMetUpdate counts the number of peer meta updates
|
||||||
|
func (metrics *AccountManagerMetrics) CountPeerMetUpdate() {
|
||||||
|
metrics.peerMetaUpdateCount.Add(metrics.ctx, 1)
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type StoreMetrics struct {
|
|||||||
globalLockAcquisitionDurationMs metric.Int64Histogram
|
globalLockAcquisitionDurationMs metric.Int64Histogram
|
||||||
persistenceDurationMicro metric.Int64Histogram
|
persistenceDurationMicro metric.Int64Histogram
|
||||||
persistenceDurationMs metric.Int64Histogram
|
persistenceDurationMs metric.Int64Histogram
|
||||||
|
transactionDurationMs metric.Int64Histogram
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +41,17 @@ func NewStoreMetrics(ctx context.Context, meter metric.Meter) (*StoreMetrics, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transactionDurationMs, err := meter.Int64Histogram("management.store.transaction.duration.ms")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &StoreMetrics{
|
return &StoreMetrics{
|
||||||
globalLockAcquisitionDurationMicro: globalLockAcquisitionDurationMicro,
|
globalLockAcquisitionDurationMicro: globalLockAcquisitionDurationMicro,
|
||||||
globalLockAcquisitionDurationMs: globalLockAcquisitionDurationMs,
|
globalLockAcquisitionDurationMs: globalLockAcquisitionDurationMs,
|
||||||
persistenceDurationMicro: persistenceDurationMicro,
|
persistenceDurationMicro: persistenceDurationMicro,
|
||||||
persistenceDurationMs: persistenceDurationMs,
|
persistenceDurationMs: persistenceDurationMs,
|
||||||
|
transactionDurationMs: transactionDurationMs,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -60,3 +67,8 @@ func (metrics *StoreMetrics) CountPersistenceDuration(duration time.Duration) {
|
|||||||
metrics.persistenceDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
metrics.persistenceDurationMicro.Record(metrics.ctx, duration.Microseconds())
|
||||||
metrics.persistenceDurationMs.Record(metrics.ctx, duration.Milliseconds())
|
metrics.persistenceDurationMs.Record(metrics.ctx, duration.Milliseconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountTransactionDuration counts the duration of a store persistence operation
|
||||||
|
func (metrics *StoreMetrics) CountTransactionDuration(duration time.Duration) {
|
||||||
|
metrics.transactionDurationMs.Record(metrics.ctx, duration.Milliseconds())
|
||||||
|
}
|
||||||
|
|||||||
@@ -805,15 +805,20 @@ func (am *DefaultAccountManager) SaveOrAddUsers(ctx context.Context, accountID,
|
|||||||
expiredPeers = append(expiredPeers, blockedPeers...)
|
expiredPeers = append(expiredPeers, blockedPeers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
peerGroupsAdded := make(map[string][]string)
|
||||||
|
peerGroupsRemoved := make(map[string][]string)
|
||||||
if update.AutoGroups != nil && account.Settings.GroupsPropagationEnabled {
|
if update.AutoGroups != nil && account.Settings.GroupsPropagationEnabled {
|
||||||
removedGroups := difference(oldUser.AutoGroups, update.AutoGroups)
|
removedGroups := difference(oldUser.AutoGroups, update.AutoGroups)
|
||||||
// need force update all auto groups in any case they will not be duplicated
|
// need force update all auto groups in any case they will not be duplicated
|
||||||
account.UserGroupsAddToPeers(oldUser.Id, update.AutoGroups...)
|
peerGroupsAdded = account.UserGroupsAddToPeers(oldUser.Id, update.AutoGroups...)
|
||||||
account.UserGroupsRemoveFromPeers(oldUser.Id, removedGroups...)
|
peerGroupsRemoved = account.UserGroupsRemoveFromPeers(oldUser.Id, removedGroups...)
|
||||||
}
|
}
|
||||||
|
|
||||||
events := am.prepareUserUpdateEvents(ctx, initiatorUser.Id, oldUser, newUser, account, transferredOwnerRole)
|
userUpdateEvents := am.prepareUserUpdateEvents(ctx, initiatorUser.Id, oldUser, newUser, account, transferredOwnerRole)
|
||||||
eventsToStore = append(eventsToStore, events...)
|
eventsToStore = append(eventsToStore, userUpdateEvents...)
|
||||||
|
|
||||||
|
userGroupsEvents := am.prepareUserGroupsEvents(ctx, initiatorUser.Id, oldUser, newUser, account, peerGroupsAdded, peerGroupsRemoved)
|
||||||
|
eventsToStore = append(eventsToStore, userGroupsEvents...)
|
||||||
|
|
||||||
updatedUserInfo, err := getUserInfo(ctx, am, newUser, account)
|
updatedUserInfo, err := getUserInfo(ctx, am, newUser, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -872,32 +877,78 @@ func (am *DefaultAccountManager) prepareUserUpdateEvents(ctx context.Context, in
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return eventsToStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *DefaultAccountManager) prepareUserGroupsEvents(ctx context.Context, initiatorUserID string, oldUser, newUser *User, account *Account, peerGroupsAdded, peerGroupsRemoved map[string][]string) []func() {
|
||||||
|
var eventsToStore []func()
|
||||||
if newUser.AutoGroups != nil {
|
if newUser.AutoGroups != nil {
|
||||||
removedGroups := difference(oldUser.AutoGroups, newUser.AutoGroups)
|
removedGroups := difference(oldUser.AutoGroups, newUser.AutoGroups)
|
||||||
addedGroups := difference(newUser.AutoGroups, oldUser.AutoGroups)
|
addedGroups := difference(newUser.AutoGroups, oldUser.AutoGroups)
|
||||||
for _, g := range removedGroups {
|
|
||||||
group := account.GetGroup(g)
|
|
||||||
if group != nil {
|
|
||||||
eventsToStore = append(eventsToStore, func() {
|
|
||||||
am.StoreEvent(ctx, initiatorUserID, oldUser.Id, account.Id, activity.GroupRemovedFromUser,
|
|
||||||
map[string]any{"group": group.Name, "group_id": group.ID, "is_service_user": newUser.IsServiceUser, "user_name": newUser.ServiceUserName})
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
removedEvents := am.handleGroupRemovedFromUser(ctx, initiatorUserID, oldUser, newUser, account, removedGroups, peerGroupsRemoved)
|
||||||
log.WithContext(ctx).Errorf("group %s not found while saving user activity event of account %s", g, account.Id)
|
eventsToStore = append(eventsToStore, removedEvents...)
|
||||||
}
|
|
||||||
}
|
addedEvents := am.handleGroupAddedToUser(ctx, initiatorUserID, oldUser, newUser, account, addedGroups, peerGroupsAdded)
|
||||||
for _, g := range addedGroups {
|
eventsToStore = append(eventsToStore, addedEvents...)
|
||||||
group := account.GetGroup(g)
|
}
|
||||||
if group != nil {
|
return eventsToStore
|
||||||
eventsToStore = append(eventsToStore, func() {
|
}
|
||||||
am.StoreEvent(ctx, initiatorUserID, oldUser.Id, account.Id, activity.GroupAddedToUser,
|
|
||||||
map[string]any{"group": group.Name, "group_id": group.ID, "is_service_user": newUser.IsServiceUser, "user_name": newUser.ServiceUserName})
|
func (am *DefaultAccountManager) handleGroupAddedToUser(ctx context.Context, initiatorUserID string, oldUser, newUser *User, account *Account, addedGroups []string, peerGroupsAdded map[string][]string) []func() {
|
||||||
})
|
var eventsToStore []func()
|
||||||
}
|
for _, g := range addedGroups {
|
||||||
|
group := account.GetGroup(g)
|
||||||
|
if group != nil {
|
||||||
|
eventsToStore = append(eventsToStore, func() {
|
||||||
|
am.StoreEvent(ctx, initiatorUserID, oldUser.Id, account.Id, activity.GroupAddedToUser,
|
||||||
|
map[string]any{"group": group.Name, "group_id": group.ID, "is_service_user": newUser.IsServiceUser, "user_name": newUser.ServiceUserName})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for groupID, peerIDs := range peerGroupsAdded {
|
||||||
|
group := account.GetGroup(groupID)
|
||||||
|
for _, peerID := range peerIDs {
|
||||||
|
peer := account.GetPeer(peerID)
|
||||||
|
eventsToStore = append(eventsToStore, func() {
|
||||||
|
meta := map[string]any{
|
||||||
|
"group": group.Name, "group_id": group.ID,
|
||||||
|
"peer_ip": peer.IP.String(), "peer_fqdn": peer.FQDN(am.GetDNSDomain()),
|
||||||
|
}
|
||||||
|
am.StoreEvent(ctx, activity.SystemInitiator, peer.ID, account.Id, activity.GroupAddedToPeer, meta)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return eventsToStore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (am *DefaultAccountManager) handleGroupRemovedFromUser(ctx context.Context, initiatorUserID string, oldUser, newUser *User, account *Account, removedGroups []string, peerGroupsRemoved map[string][]string) []func() {
|
||||||
|
var eventsToStore []func()
|
||||||
|
for _, g := range removedGroups {
|
||||||
|
group := account.GetGroup(g)
|
||||||
|
if group != nil {
|
||||||
|
eventsToStore = append(eventsToStore, func() {
|
||||||
|
am.StoreEvent(ctx, initiatorUserID, oldUser.Id, account.Id, activity.GroupRemovedFromUser,
|
||||||
|
map[string]any{"group": group.Name, "group_id": group.ID, "is_service_user": newUser.IsServiceUser, "user_name": newUser.ServiceUserName})
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.WithContext(ctx).Errorf("group %s not found while saving user activity event of account %s", g, account.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for groupID, peerIDs := range peerGroupsRemoved {
|
||||||
|
group := account.GetGroup(groupID)
|
||||||
|
for _, peerID := range peerIDs {
|
||||||
|
peer := account.GetPeer(peerID)
|
||||||
|
eventsToStore = append(eventsToStore, func() {
|
||||||
|
meta := map[string]any{
|
||||||
|
"group": group.Name, "group_id": group.ID,
|
||||||
|
"peer_ip": peer.IP.String(), "peer_fqdn": peer.FQDN(am.GetDNSDomain()),
|
||||||
|
}
|
||||||
|
am.StoreEvent(ctx, activity.SystemInitiator, peer.ID, account.Id, activity.GroupRemovedFromPeer, meta)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
return eventsToStore
|
return eventsToStore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package grpc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
"net"
|
"net"
|
||||||
"os/user"
|
"os/user"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -23,20 +26,22 @@ func WithCustomDialer() grpc.DialOption {
|
|||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
currentUser, err := user.Current()
|
currentUser, err := user.Current()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to get current user: %v", err)
|
return nil, status.Errorf(codes.FailedPrecondition, "failed to get current user: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// the custom dialer requires root permissions which are not required for use cases run as non-root
|
// the custom dialer requires root permissions which are not required for use cases run as non-root
|
||||||
if currentUser.Uid != "0" {
|
if currentUser.Uid != "0" {
|
||||||
|
log.Debug("Not running as root, using standard dialer")
|
||||||
dialer := &net.Dialer{}
|
dialer := &net.Dialer{}
|
||||||
return dialer.DialContext(ctx, "tcp", addr)
|
return dialer.DialContext(ctx, "tcp", addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("Using nbnet.NewDialer()")
|
||||||
conn, err := nbnet.NewDialer().DialContext(ctx, "tcp", addr)
|
conn, err := nbnet.NewDialer().DialContext(ctx, "tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to dial: %s", err)
|
log.Errorf("Failed to dial: %s", err)
|
||||||
return nil, err
|
return nil, fmt.Errorf("nbnet.NewDialer().DialContext: %w", err)
|
||||||
}
|
}
|
||||||
return conn, nil
|
return conn, nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.
|
|||||||
|
|
||||||
conn, err := d.Dialer.DialContext(ctx, network, address)
|
conn, err := d.Dialer.DialContext(ctx, network, address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("dial: %w", err)
|
return nil, fmt.Errorf("d.Dialer.DialContext: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap the connection in Conn to handle Close with hooks
|
// Wrap the connection in Conn to handle Close with hooks
|
||||||
|
|||||||
@@ -4,9 +4,14 @@ package net
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const EnvSkipSocketMark = "NB_SKIP_SOCKET_MARK"
|
||||||
|
|
||||||
// SetSocketMark sets the SO_MARK option on the given socket connection
|
// SetSocketMark sets the SO_MARK option on the given socket connection
|
||||||
func SetSocketMark(conn syscall.Conn) error {
|
func SetSocketMark(conn syscall.Conn) error {
|
||||||
sysconn, err := conn.SyscallConn()
|
sysconn, err := conn.SyscallConn()
|
||||||
@@ -36,6 +41,13 @@ func SetRawSocketMark(conn syscall.RawConn) error {
|
|||||||
|
|
||||||
func SetSocketOpt(fd int) error {
|
func SetSocketOpt(fd int) error {
|
||||||
if CustomRoutingDisabled() {
|
if CustomRoutingDisabled() {
|
||||||
|
log.Infof("Custom routing is disabled, skipping SO_MARK")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the new environment variable
|
||||||
|
if skipSocketMark := os.Getenv(EnvSkipSocketMark); skipSocketMark == "true" {
|
||||||
|
log.Info("NB_SKIP_SOCKET_MARK is set to true, skipping SO_MARK")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user