mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-05 13:09:07 +02:00
Merge branch 'main' into feat/network-map-serial
This commit is contained in:
@@ -18,6 +18,13 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/netbirdio/management-integrations/integrations"
|
||||
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/controller"
|
||||
"github.com/netbirdio/netbird/management/internals/controllers/network_map/update_channel"
|
||||
"github.com/netbirdio/netbird/management/internals/modules/peers"
|
||||
"github.com/netbirdio/netbird/management/internals/modules/peers/ephemeral/manager"
|
||||
nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
|
||||
|
||||
"github.com/netbirdio/netbird/client/system"
|
||||
"github.com/netbirdio/netbird/encryption"
|
||||
"github.com/netbirdio/netbird/management/internals/server/config"
|
||||
@@ -26,7 +33,6 @@ import (
|
||||
"github.com/netbirdio/netbird/management/server/groups"
|
||||
"github.com/netbirdio/netbird/management/server/integrations/port_forwarding"
|
||||
"github.com/netbirdio/netbird/management/server/mock_server"
|
||||
"github.com/netbirdio/netbird/management/server/peers"
|
||||
"github.com/netbirdio/netbird/management/server/permissions"
|
||||
"github.com/netbirdio/netbird/management/server/settings"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@@ -66,7 +72,6 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
||||
}
|
||||
t.Cleanup(cleanUp)
|
||||
|
||||
peersUpdateManager := mgmt.NewPeersUpdateManager(nil)
|
||||
eventStore := &activity.InMemoryEventStore{}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
@@ -109,15 +114,22 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
||||
Return(&types.ExtraSettings{}, nil).
|
||||
AnyTimes()
|
||||
|
||||
accountManager, err := mgmt.BuildManager(context.Background(), store, peersUpdateManager, nil, "", "netbird.selfhosted", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false)
|
||||
ctx := context.Background()
|
||||
updateManager := update_channel.NewPeersUpdateManager(metrics)
|
||||
requestBuffer := mgmt.NewAccountRequestBuffer(ctx, store)
|
||||
networkMapController := controller.NewController(ctx, store, metrics, updateManager, requestBuffer, mgmt.MockIntegratedValidator{}, settingsMockManager, "netbird.selfhosted", port_forwarding.NewControllerMock(), manager.NewEphemeralManager(store, peersManger), config)
|
||||
accountManager, err := mgmt.BuildManager(context.Background(), config, store, networkMapController, nil, "", eventStore, nil, false, ia, metrics, port_forwarding.NewControllerMock(), settingsMockManager, permissionsManagerMock, false)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
groupsManager := groups.NewManagerMock()
|
||||
|
||||
secretsManager := mgmt.NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig, config.Relay, settingsMockManager, groupsManager)
|
||||
mgmtServer, err := mgmt.NewServer(context.Background(), config, accountManager, settingsMockManager, peersUpdateManager, secretsManager, nil, nil, nil, mgmt.MockIntegratedValidator{})
|
||||
secretsManager, err := nbgrpc.NewTimeBasedAuthSecretsManager(updateManager, config.TURNConfig, config.Relay, settingsMockManager, groupsManager)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
mgmtServer, err := nbgrpc.NewServer(config, accountManager, settingsMockManager, secretsManager, nil, nil, mgmt.MockIntegratedValidator{}, networkMapController)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -301,7 +313,7 @@ func TestClient_Sync(t *testing.T) {
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
err = client.Sync(ctx, info, func(msg *mgmtProto.SyncResponse) error {
|
||||
err = client.Sync(ctx, info, 0, func(msg *mgmtProto.SyncResponse) error {
|
||||
ch <- msg
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
package common
|
||||
|
||||
// LoginFlag introduces additional login flags to the PKCE authorization request
|
||||
// LoginFlag introduces additional login flags to the PKCE authorization request.
|
||||
//
|
||||
// # Config Values
|
||||
//
|
||||
// | Value | Flag | OAuth Parameters |
|
||||
// |-------|----------------------|-----------------------------------------|
|
||||
// | 0 | LoginFlagPromptLogin | prompt=login |
|
||||
// | 1 | LoginFlagMaxAge0 | max_age=0 |
|
||||
type LoginFlag uint8
|
||||
|
||||
const (
|
||||
// LoginFlagPrompt adds prompt=login to the authorization request
|
||||
LoginFlagPrompt LoginFlag = iota
|
||||
// LoginFlagPromptLogin adds prompt=login to the authorization request
|
||||
LoginFlagPromptLogin LoginFlag = iota
|
||||
// LoginFlagMaxAge0 adds max_age=0 to the authorization request
|
||||
LoginFlagMaxAge0
|
||||
// LoginFlagNone disables all login flags
|
||||
LoginFlagNone
|
||||
)
|
||||
|
||||
func (l LoginFlag) IsPromptLogin() bool {
|
||||
return l == LoginFlagPrompt
|
||||
}
|
||||
|
||||
func (l LoginFlag) IsMaxAge0Login() bool {
|
||||
return l == LoginFlagMaxAge0
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/netbirdio/netbird/encryption"
|
||||
"github.com/netbirdio/netbird/shared/management/domain"
|
||||
"github.com/netbirdio/netbird/shared/management/proto"
|
||||
"github.com/netbirdio/netbird/util/wsproxy"
|
||||
)
|
||||
|
||||
const ConnectTimeout = 10 * time.Second
|
||||
@@ -52,10 +53,9 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
|
||||
|
||||
operation := func() error {
|
||||
var err error
|
||||
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled)
|
||||
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent)
|
||||
if err != nil {
|
||||
log.Printf("createConnection error: %v", err)
|
||||
return err
|
||||
return fmt.Errorf("create connection: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGrpcClient_LastNetworkMapSerial_SetGet(t *testing.T) {
|
||||
c := &GrpcClient{}
|
||||
|
||||
if got := c.getLastNetworkMapSerial(); got != 0 {
|
||||
t.Fatalf("initial serial should be 0, got %d", got)
|
||||
}
|
||||
|
||||
c.setLastNetworkMapSerial(123)
|
||||
if got := c.getLastNetworkMapSerial(); got != 123 {
|
||||
t.Fatalf("serial after set should be 123, got %d", got)
|
||||
}
|
||||
|
||||
// overwrite should work
|
||||
c.setLastNetworkMapSerial(5)
|
||||
if got := c.getLastNetworkMapSerial(); got != 5 {
|
||||
t.Fatalf("serial after overwrite should be 5, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,14 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
)
|
||||
|
||||
// ErrGroupNotFound is returned when a group is not found
|
||||
var ErrGroupNotFound = errors.New("group not found")
|
||||
|
||||
// GroupsAPI APIs for Groups, do not use directly
|
||||
type GroupsAPI struct {
|
||||
c *Client
|
||||
@@ -27,6 +31,27 @@ func (a *GroupsAPI) List(ctx context.Context) ([]api.Group, error) {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// GetByName get group by name
|
||||
// See more: https://docs.netbird.io/api/resources/groups#list-all-groups
|
||||
func (a *GroupsAPI) GetByName(ctx context.Context, groupName string) (*api.Group, error) {
|
||||
params := map[string]string{"name": groupName}
|
||||
resp, err := a.c.NewRequest(ctx, "GET", "/api/groups", nil, params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.Body != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
ret, err := parseResponse[[]api.Group](resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ret) == 0 {
|
||||
return nil, ErrGroupNotFound
|
||||
}
|
||||
return &ret[0], nil
|
||||
}
|
||||
|
||||
// Get get group info
|
||||
// See more: https://docs.netbird.io/api/resources/groups#retrieve-a-group
|
||||
func (a *GroupsAPI) Get(ctx context.Context, groupID string) (*api.Group, error) {
|
||||
|
||||
@@ -463,6 +463,9 @@ components:
|
||||
description: (Cloud only) Indicates whether peer needs approval
|
||||
type: boolean
|
||||
example: true
|
||||
disapproval_reason:
|
||||
description: (Cloud only) Reason why the peer requires approval
|
||||
type: string
|
||||
country_code:
|
||||
$ref: '#/components/schemas/CountryCode'
|
||||
city_name:
|
||||
@@ -507,6 +510,48 @@ components:
|
||||
- serial_number
|
||||
- extra_dns_labels
|
||||
- ephemeral
|
||||
PeerTemporaryAccessRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
description: Peer's hostname
|
||||
type: string
|
||||
example: temp-host-1
|
||||
wg_pub_key:
|
||||
description: Peer's WireGuard public key
|
||||
type: string
|
||||
example: "n0r3pL4c3h0ld3rK3y=="
|
||||
rules:
|
||||
description: List of temporary access rules
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: "tcp/80"
|
||||
required:
|
||||
- name
|
||||
- wg_pub_key
|
||||
- rules
|
||||
PeerTemporaryAccessResponse:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
description: Peer's hostname
|
||||
type: string
|
||||
example: temp-host-1
|
||||
id:
|
||||
description: Peer ID
|
||||
type: string
|
||||
example: chacbco6lnnbn6cg5s90
|
||||
rules:
|
||||
description: List of temporary access rules
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: "tcp/80"
|
||||
required:
|
||||
- name
|
||||
- id
|
||||
- rules
|
||||
AccessiblePeer:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/PeerMinimum'
|
||||
@@ -1404,7 +1449,8 @@ components:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/NetworkResourceType'
|
||||
- type: string
|
||||
example: host
|
||||
enum: ["peer"]
|
||||
example: peer
|
||||
NetworkRequest:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2793,6 +2839,42 @@ paths:
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
"$ref": "#/components/responses/internal_error"
|
||||
/api/peers/{peerId}/temporary-access:
|
||||
post:
|
||||
summary: Create a Temporary Access Peer
|
||||
description: Creates a temporary access peer that can be used to access this peer and this peer only. The temporary access peer and its access policies will be automatically deleted after it disconnects.
|
||||
tags: [ Peers ]
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: path
|
||||
name: peerId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a peer
|
||||
requestBody:
|
||||
description: Temporary Access Peer create request
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/PeerTemporaryAccessRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Temporary Access Peer response
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PeerTemporaryAccessResponse'
|
||||
'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:
|
||||
get:
|
||||
x-cloud-only: true
|
||||
@@ -3280,6 +3362,14 @@ paths:
|
||||
security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
parameters:
|
||||
- in: query
|
||||
name: name
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
description: Filter groups by name (exact match)
|
||||
example: "devs"
|
||||
responses:
|
||||
'200':
|
||||
description: A JSON Array of Groups
|
||||
@@ -3293,6 +3383,8 @@ paths:
|
||||
"$ref": "#/components/responses/bad_request"
|
||||
'401':
|
||||
"$ref": "#/components/responses/requires_authentication"
|
||||
'404':
|
||||
"$ref": "#/components/responses/not_found"
|
||||
'403':
|
||||
"$ref": "#/components/responses/forbidden"
|
||||
'500':
|
||||
|
||||
@@ -168,6 +168,7 @@ const (
|
||||
const (
|
||||
ResourceTypeDomain ResourceType = "domain"
|
||||
ResourceTypeHost ResourceType = "host"
|
||||
ResourceTypePeer ResourceType = "peer"
|
||||
ResourceTypeSubnet ResourceType = "subnet"
|
||||
)
|
||||
|
||||
@@ -1036,6 +1037,9 @@ type Peer struct {
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// DisapprovalReason (Cloud only) Reason why the peer requires approval
|
||||
DisapprovalReason *string `json:"disapproval_reason,omitempty"`
|
||||
|
||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||
DnsLabel string `json:"dns_label"`
|
||||
|
||||
@@ -1123,6 +1127,9 @@ type PeerBatch struct {
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// DisapprovalReason (Cloud only) Reason why the peer requires approval
|
||||
DisapprovalReason *string `json:"disapproval_reason,omitempty"`
|
||||
|
||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||
DnsLabel string `json:"dns_label"`
|
||||
|
||||
@@ -1221,6 +1228,30 @@ type PeerRequest struct {
|
||||
SshEnabled bool `json:"ssh_enabled"`
|
||||
}
|
||||
|
||||
// PeerTemporaryAccessRequest defines model for PeerTemporaryAccessRequest.
|
||||
type PeerTemporaryAccessRequest struct {
|
||||
// Name Peer's hostname
|
||||
Name string `json:"name"`
|
||||
|
||||
// Rules List of temporary access rules
|
||||
Rules []string `json:"rules"`
|
||||
|
||||
// WgPubKey Peer's WireGuard public key
|
||||
WgPubKey string `json:"wg_pub_key"`
|
||||
}
|
||||
|
||||
// PeerTemporaryAccessResponse defines model for PeerTemporaryAccessResponse.
|
||||
type PeerTemporaryAccessResponse struct {
|
||||
// Id Peer ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// Name Peer's hostname
|
||||
Name string `json:"name"`
|
||||
|
||||
// Rules List of temporary access rules
|
||||
Rules []string `json:"rules"`
|
||||
}
|
||||
|
||||
// PersonalAccessToken defines model for PersonalAccessToken.
|
||||
type PersonalAccessToken struct {
|
||||
// CreatedAt Date the token was created
|
||||
@@ -1877,6 +1908,12 @@ type GetApiEventsNetworkTrafficParamsConnectionType string
|
||||
// GetApiEventsNetworkTrafficParamsDirection defines parameters for GetApiEventsNetworkTraffic.
|
||||
type GetApiEventsNetworkTrafficParamsDirection string
|
||||
|
||||
// GetApiGroupsParams defines parameters for GetApiGroups.
|
||||
type GetApiGroupsParams struct {
|
||||
// Name Filter groups by name (exact match)
|
||||
Name *string `form:"name,omitempty" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
// GetApiPeersParams defines parameters for GetApiPeers.
|
||||
type GetApiPeersParams struct {
|
||||
// Name Filter peers by name
|
||||
@@ -1949,6 +1986,9 @@ type PostApiPeersPeerIdIngressPortsJSONRequestBody = IngressPortAllocationReques
|
||||
// PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody defines body for PutApiPeersPeerIdIngressPortsAllocationId for application/json ContentType.
|
||||
type PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody = IngressPortAllocationRequest
|
||||
|
||||
// PostApiPeersPeerIdTemporaryAccessJSONRequestBody defines body for PostApiPeersPeerIdTemporaryAccess for application/json ContentType.
|
||||
type PostApiPeersPeerIdTemporaryAccessJSONRequestBody = PeerTemporaryAccessRequest
|
||||
|
||||
// PostApiPoliciesJSONRequestBody defines body for PostApiPolicies for application/json ContentType.
|
||||
type PostApiPoliciesJSONRequestBody = PolicyUpdate
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ func WriteError(ctx context.Context, err error, w http.ResponseWriter) {
|
||||
httpStatus = http.StatusUnauthorized
|
||||
case status.BadRequest:
|
||||
httpStatus = http.StatusBadRequest
|
||||
case status.TooManyRequests:
|
||||
httpStatus = http.StatusTooManyRequests
|
||||
default:
|
||||
}
|
||||
msg = strings.ToLower(err.Error())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package operations
|
||||
|
||||
// Operation represents a permission operation type
|
||||
type Operation string
|
||||
type Operation string
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -151,6 +151,12 @@ message Flags {
|
||||
bool blockInbound = 9;
|
||||
|
||||
bool lazyConnectionEnabled = 10;
|
||||
|
||||
bool enableSSHRoot = 11;
|
||||
bool enableSSHSFTP = 12;
|
||||
bool enableSSHLocalPortForwarding = 13;
|
||||
bool enableSSHRemotePortForwarding = 14;
|
||||
bool disableSSHAuth = 15;
|
||||
}
|
||||
|
||||
// PeerSystemMeta is machine meta data like OS and version.
|
||||
@@ -245,6 +251,14 @@ message FlowConfig {
|
||||
bool dnsCollection = 8;
|
||||
}
|
||||
|
||||
// JWTConfig represents JWT authentication configuration
|
||||
message JWTConfig {
|
||||
string issuer = 1;
|
||||
string audience = 2;
|
||||
string keysLocation = 3;
|
||||
int64 maxTokenAge = 4;
|
||||
}
|
||||
|
||||
// ProtectedHostConfig is similar to HostConfig but has additional user and password
|
||||
// Mostly used for TURN servers
|
||||
message ProtectedHostConfig {
|
||||
@@ -340,6 +354,8 @@ message SSHConfig {
|
||||
// sshPubKey is a SSH public key of a peer to be added to authorized_hosts.
|
||||
// This property should be ignore if SSHConfig comes from PeerConfig.
|
||||
bytes sshPubKey = 2;
|
||||
|
||||
JWTConfig jwtConfig = 3;
|
||||
}
|
||||
|
||||
// DeviceAuthorizationFlowRequest empty struct for future expansion
|
||||
@@ -415,12 +431,15 @@ message DNSConfig {
|
||||
bool ServiceEnable = 1;
|
||||
repeated NameServerGroup NameServerGroups = 2;
|
||||
repeated CustomZone CustomZones = 3;
|
||||
int64 ForwarderPort = 4 [deprecated = true];
|
||||
}
|
||||
|
||||
// CustomZone represents a dns.CustomZone
|
||||
message CustomZone {
|
||||
string Domain = 1;
|
||||
repeated SimpleRecord Records = 2;
|
||||
bool SearchDomainDisabled = 3;
|
||||
bool SkipPTRProcess = 4;
|
||||
}
|
||||
|
||||
// SimpleRecord represents a dns.SimpleRecord
|
||||
|
||||
@@ -37,6 +37,9 @@ const (
|
||||
|
||||
// Unauthenticated indicates that user is not authenticated due to absence of valid credentials
|
||||
Unauthenticated Type = 10
|
||||
|
||||
// TooManyRequests indicates that the user has sent too many requests in a given amount of time (rate limiting)
|
||||
TooManyRequests Type = 11
|
||||
)
|
||||
|
||||
// Type is a type of the Error
|
||||
|
||||
Reference in New Issue
Block a user