mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-23 05:49:07 +02:00
Merge branch 'main' into agent-network/provider-credential-check
This commit is contained in:
@@ -21,8 +21,7 @@ import (
|
||||
"google.golang.org/grpc/connectivity"
|
||||
|
||||
nbgrpc "github.com/netbirdio/netbird/client/grpc"
|
||||
"github.com/netbirdio/netbird/client/netstate"
|
||||
"github.com/netbirdio/netbird/client/netsweep"
|
||||
"github.com/netbirdio/netbird/client/netevents"
|
||||
"github.com/netbirdio/netbird/client/system"
|
||||
"github.com/netbirdio/netbird/encryption"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
@@ -64,12 +63,9 @@ type GrpcClient struct {
|
||||
connStateCallbackLock sync.RWMutex
|
||||
serverURL string
|
||||
|
||||
// netState gates the stream retry loop on OS-reported network
|
||||
// availability; nil (the default) disables gating.
|
||||
netState *netstate.State
|
||||
|
||||
// sweeper cuts the transport connections on network change; nil disables it.
|
||||
sweeper *netsweep.Sweeper
|
||||
// netMgr gates the stream retry loop on OS-reported network
|
||||
// availability and sweeps the transport on network change.
|
||||
netMgr *netevents.Manager
|
||||
|
||||
// syncStreamErr holds the last Sync stream error, or nil while the stream
|
||||
// is established and healthy. GetServerKey succeeds even when the peer
|
||||
@@ -123,15 +119,9 @@ func MaxRecvMsgSize() int {
|
||||
// Option configures optional GrpcClient behavior.
|
||||
type Option func(*GrpcClient)
|
||||
|
||||
// WithNetworkState injects the OS network availability state that gates the
|
||||
// stream retry loop; without it gating is disabled.
|
||||
func WithNetworkState(netState *netstate.State) Option {
|
||||
return func(c *GrpcClient) { c.netState = netState }
|
||||
}
|
||||
|
||||
// WithSweeper injects the network change sweeper.
|
||||
func WithSweeper(sweeper *netsweep.Sweeper) Option {
|
||||
return func(c *GrpcClient) { c.sweeper = sweeper }
|
||||
// WithNetEvents injects the OS network event handling.
|
||||
func WithNetEvents(events *netevents.Manager) Option {
|
||||
return func(c *GrpcClient) { c.netMgr = events }
|
||||
}
|
||||
|
||||
// NewClient creates a new client to Management service
|
||||
@@ -152,8 +142,8 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
|
||||
extraOpts = append(extraOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxSize)))
|
||||
log.Infof("management gRPC max receive message size set to %d bytes", maxSize)
|
||||
}
|
||||
if c.sweeper != nil {
|
||||
extraOpts = append(extraOpts, nbgrpc.WithSweeper(c.sweeper))
|
||||
if c.netMgr != nil {
|
||||
extraOpts = append(extraOpts, nbgrpc.WithSweeper(c.netMgr))
|
||||
}
|
||||
|
||||
var conn *grpc.ClientConn
|
||||
@@ -235,16 +225,19 @@ func (c *GrpcClient) withMgmtStream(
|
||||
ctx context.Context,
|
||||
handler func(ctx context.Context, serverPubKey wgtypes.Key, backOff backoff.BackOff) error,
|
||||
) error {
|
||||
backOff := c.sweeper.QuickRetryBackoff(ctx, defaultBackoff(ctx), c.netState)
|
||||
backOff := c.netMgr.QuickRetryBackoff(ctx, defaultBackoff(ctx))
|
||||
operation := func() error {
|
||||
// suspend reconnect attempts while the OS reports no usable network.
|
||||
// Wait only errors on a cancelled context, which means shutdown, so
|
||||
// stop the loop without reporting a failure.
|
||||
if waited, err := c.netState.Wait(ctx); err != nil {
|
||||
if waited, err := c.netMgr.Wait(ctx); err != nil {
|
||||
log.Debugf("management connection context has been canceled while offline, this usually indicates shutdown")
|
||||
return nil //nolint:nilerr // a cancelled context means shutdown, not a retryable failure
|
||||
} else if waited {
|
||||
backOff.Reset()
|
||||
// dials attempted while offline grew the channel's internal backoff;
|
||||
// reset it too, or the reconnect waits out that timer first
|
||||
c.conn.ResetConnectBackoff()
|
||||
}
|
||||
|
||||
connState := c.conn.GetState()
|
||||
@@ -273,7 +266,7 @@ func (c *GrpcClient) withMgmtStream(
|
||||
return handler(ctx, *serverPubKey, backOff)
|
||||
}
|
||||
|
||||
err := nbgrpc.Retry(ctx, operation, backOff, c.netState)
|
||||
err := nbgrpc.Retry(ctx, operation, backOff, c.netMgr)
|
||||
if err != nil {
|
||||
log.Warnf("exiting the Management service connection retry loop due to the unrecoverable error: %s", err)
|
||||
}
|
||||
|
||||
@@ -275,6 +275,7 @@ func decodePeerCompact(pc *proto.PeerCompact, peerID string) *types.ComponentPee
|
||||
SupportsIPv6: pc.SupportsIpv6,
|
||||
ServerSSHAllowed: pc.ServerSshAllowed,
|
||||
AddedWithSSOLogin: pc.AddedWithSsoLogin,
|
||||
ProxyEmbedded: pc.ProxyEmbedded,
|
||||
}
|
||||
if pc.LastLoginUnixNano != 0 {
|
||||
peer.LastLogin = time.Unix(0, pc.LastLoginUnixNano)
|
||||
|
||||
@@ -272,8 +272,9 @@ func ToProtocolDNSConfig(update nbdns.Config, cache DNSConfigCache, forwardPort
|
||||
}
|
||||
|
||||
// AppendRemotePeerConfig appends typed peers as proto.RemotePeerConfig
|
||||
// entries to dst and returns the result.
|
||||
func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*types.ComponentPeer, dnsName string, includeIPv6 bool) []*proto.RemotePeerConfig {
|
||||
// entries to dst and returns the result. localIsProxy reports whether the peer
|
||||
// receiving this config is itself an embedded proxy.
|
||||
func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*types.ComponentPeer, dnsName string, includeIPv6 bool, localIsProxy bool) []*proto.RemotePeerConfig {
|
||||
for _, rPeer := range peers {
|
||||
allowedIPs := []string{rPeer.IP.String() + "/32"}
|
||||
if includeIPv6 && rPeer.IPv6.IsValid() {
|
||||
@@ -285,11 +286,24 @@ func AppendRemotePeerConfig(dst []*proto.RemotePeerConfig, peers []*types.Compon
|
||||
SshConfig: &proto.SSHConfig{SshPubKey: []byte(rPeer.SSHKey)},
|
||||
Fqdn: rPeer.FQDN(dnsName),
|
||||
AgentVersion: rPeer.AgentVersion,
|
||||
LazyState: lazyStateFor(localIsProxy, rPeer),
|
||||
})
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// lazyStateFor returns the per-peer lazy override for a remote peer. Connections
|
||||
// involving an ephemeral proxy peer on either endpoint default to lazy so shared
|
||||
// proxy infrastructure is not kept permanently connected to every peer. All
|
||||
// other peers follow the account-wide flag. A future admin-facing per-peer
|
||||
// setting can return LazyStateEager here to force a peer always-active.
|
||||
func lazyStateFor(localIsProxy bool, rPeer *types.ComponentPeer) proto.LazyState {
|
||||
if localIsProxy || rPeer.ProxyEmbedded {
|
||||
return proto.LazyState_LazyStateLazy
|
||||
}
|
||||
return proto.LazyState_LazyStateDefault
|
||||
}
|
||||
|
||||
// BuildAuthorizedUsersProto deduplicates user-IDs into a hashed list and
|
||||
// builds per-machine-user index maps. Returns (hashedUsers, machineUsers).
|
||||
// Errors from individual hash failures are logged via the provided context;
|
||||
|
||||
@@ -74,11 +74,11 @@ func EnvelopeToNetworkMap(ctx context.Context, env *proto.NetworkMapEnvelope, lo
|
||||
protoNM.Routes = ToProtocolRoutes(typedNM.Routes)
|
||||
protoNM.DNSConfig = ToProtocolDNSConfig(typedNM.DNSConfig, nil, dnsFwdPort)
|
||||
|
||||
remotePeers := AppendRemotePeerConfig(nil, typedNM.Peers, dnsName, includeIPv6)
|
||||
remotePeers := AppendRemotePeerConfig(nil, typedNM.Peers, dnsName, includeIPv6, localPeer.ProxyEmbedded)
|
||||
protoNM.RemotePeers = remotePeers
|
||||
protoNM.RemotePeersIsEmpty = len(remotePeers) == 0
|
||||
|
||||
protoNM.OfflinePeers = AppendRemotePeerConfig(nil, typedNM.OfflinePeers, dnsName, includeIPv6)
|
||||
protoNM.OfflinePeers = AppendRemotePeerConfig(nil, typedNM.OfflinePeers, dnsName, includeIPv6, localPeer.ProxyEmbedded)
|
||||
|
||||
firewallRules := ToProtocolFirewallRules(typedNM.FirewallRules, includeIPv6, useSourcePrefixes)
|
||||
protoNM.FirewallRules = firewallRules
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -501,6 +501,22 @@ message RemotePeerConfig {
|
||||
string fqdn = 4;
|
||||
|
||||
string agentVersion = 5;
|
||||
|
||||
// lazyState is the management per-peer override for lazy (on-demand)
|
||||
// connections to this remote peer. LazyStateDefault follows the account-wide
|
||||
// flag; LazyStateLazy forces lazy; LazyStateEager forces an always-active
|
||||
// connection. A local NB_LAZY_CONN/MDM override still wins over this.
|
||||
LazyState lazyState = 6;
|
||||
}
|
||||
|
||||
// LazyState is the management per-peer override for lazy connections.
|
||||
enum LazyState {
|
||||
// Follow the account-wide lazy connection flag.
|
||||
LazyStateDefault = 0;
|
||||
// Force a lazy (on-demand) connection regardless of the account flag.
|
||||
LazyStateLazy = 1;
|
||||
// Force an always-active connection regardless of the account flag.
|
||||
LazyStateEager = 2;
|
||||
}
|
||||
|
||||
// SSHConfig represents SSH configurations of a peer.
|
||||
@@ -1016,6 +1032,11 @@ message PeerCompact {
|
||||
// (port 22022) is only added when this flag is set and the peer agent
|
||||
// version supports it.
|
||||
bool server_ssh_allowed = 13;
|
||||
|
||||
// Mirror of types.Peer.ProxyMeta.Embedded. Connections involving an
|
||||
// ephemeral proxy peer on either endpoint default to lazy, so this bit
|
||||
// feeds the per-peer lazyState emitted in RemotePeerConfig.
|
||||
bool proxy_embedded = 14;
|
||||
}
|
||||
|
||||
// PolicyCompact is the compact form of a policy rule. Group references use
|
||||
|
||||
@@ -25,6 +25,9 @@ type ComponentPeer struct {
|
||||
LoginExpirationEnabled bool
|
||||
AddedWithSSOLogin bool
|
||||
LastLogin time.Time
|
||||
// ProxyEmbedded marks an ephemeral embedded proxy peer. Connections
|
||||
// involving such a peer on either endpoint default to lazy.
|
||||
ProxyEmbedded bool
|
||||
}
|
||||
|
||||
// FQDN returns the peer's FQDN combined of the peer's DNS label and the system's DNS domain.
|
||||
|
||||
Reference in New Issue
Block a user