mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-06 13:39:07 +02:00
Merge branch 'main' into peers-get-account-refactoring
# Conflicts: # management/server/peer.go
This commit is contained in:
@@ -1548,6 +1548,11 @@ func domainIsUpToDate(domain string, domainCategory string, claims jwtclaims.Aut
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) SyncAndMarkPeer(ctx context.Context, accountID string, peerPubKey string, meta nbpeer.PeerSystemMeta, realIP net.IP) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.WithContext(ctx).Debugf("SyncAndMarkPeer: took %v", time.Since(start))
|
||||
}()
|
||||
|
||||
accountUnlock := am.Store.AcquireReadLockByUID(ctx, accountID)
|
||||
defer accountUnlock()
|
||||
peerUnlock := am.Store.AcquireWriteLockByUID(ctx, peerPubKey)
|
||||
|
||||
@@ -463,7 +463,7 @@ func validateDeleteGroup(ctx context.Context, transaction store.Store, group *ty
|
||||
if group.Issued == types.GroupIssuedIntegration {
|
||||
executingUser, err := transaction.GetUserByUserID(ctx, store.LockingStrengthShare, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
return status.Errorf(status.Internal, "failed to get user")
|
||||
}
|
||||
if executingUser.Role != types.UserRoleAdmin || !executingUser.IsServiceUser {
|
||||
return status.Errorf(status.PermissionDenied, "only service users with admin power can delete integration group")
|
||||
@@ -505,7 +505,7 @@ func validateDeleteGroup(ctx context.Context, transaction store.Store, group *ty
|
||||
func checkGroupLinkedToSettings(ctx context.Context, transaction store.Store, group *types.Group) error {
|
||||
dnsSettings, err := transaction.GetAccountDNSSettings(ctx, store.LockingStrengthShare, group.AccountID)
|
||||
if err != nil {
|
||||
return err
|
||||
return status.Errorf(status.Internal, "failed to get DNS settings")
|
||||
}
|
||||
|
||||
if slices.Contains(dnsSettings.DisabledManagementGroups, group.ID) {
|
||||
@@ -514,7 +514,7 @@ func checkGroupLinkedToSettings(ctx context.Context, transaction store.Store, gr
|
||||
|
||||
settings, err := transaction.GetAccountSettings(ctx, store.LockingStrengthShare, group.AccountID)
|
||||
if err != nil {
|
||||
return err
|
||||
return status.Errorf(status.Internal, "failed to get account settings")
|
||||
}
|
||||
|
||||
if settings.Extra != nil && slices.Contains(settings.Extra.IntegratedValidatorGroups, group.ID) {
|
||||
|
||||
@@ -208,6 +208,8 @@ func (s *GRPCServer) Sync(req *proto.EncryptedMessage, srv proto.ManagementServi
|
||||
unlock()
|
||||
unlock = nil
|
||||
|
||||
log.WithContext(ctx).Debugf("Sync: took %v", time.Since(reqStart))
|
||||
|
||||
return s.handleUpdates(ctx, accountID, peerKey, peer, updates, srv)
|
||||
}
|
||||
|
||||
|
||||
@@ -239,8 +239,9 @@ func (h *handler) deleteGroup(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = h.accountManager.DeleteGroup(r.Context(), accountID, userID, groupID)
|
||||
if err != nil {
|
||||
_, ok := err.(*server.GroupLinkError)
|
||||
if ok {
|
||||
wrappedErr, ok := err.(interface{ Unwrap() []error })
|
||||
if ok && len(wrappedErr.Unwrap()) > 0 {
|
||||
err = wrappedErr.Unwrap()[0]
|
||||
util.WriteErrorResponse(err.Error(), http.StatusBadRequest, w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@@ -73,10 +74,12 @@ func initGroupTestData(initGroups ...*types.Group) *handler {
|
||||
},
|
||||
DeleteGroupFunc: func(_ context.Context, accountID, userId, groupID string) error {
|
||||
if groupID == "linked-grp" {
|
||||
return &server.GroupLinkError{
|
||||
err := &server.GroupLinkError{
|
||||
Resource: "something",
|
||||
Name: "linked-grp",
|
||||
}
|
||||
var allErrors error
|
||||
return errors.Join(allErrors, err)
|
||||
}
|
||||
if groupID == "invalid-grp" {
|
||||
return fmt.Errorf("internal error")
|
||||
|
||||
@@ -149,6 +149,7 @@ func NewManager(ctx context.Context, config Config, appMetrics telemetry.AppMetr
|
||||
GrantType: config.ClientConfig.GrantType,
|
||||
TokenEndpoint: config.ClientConfig.TokenEndpoint,
|
||||
ManagementEndpoint: config.ExtraConfig["ManagementEndpoint"],
|
||||
PAT: config.ExtraConfig["PAT"],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ type ZitadelClientConfig struct {
|
||||
GrantType string
|
||||
TokenEndpoint string
|
||||
ManagementEndpoint string
|
||||
PAT string
|
||||
}
|
||||
|
||||
// ZitadelCredentials zitadel authentication information.
|
||||
@@ -135,6 +136,28 @@ func readZitadelError(body io.ReadCloser) error {
|
||||
return errors.New(strings.Join(errsOut, " "))
|
||||
}
|
||||
|
||||
// verifyJWTConfig ensures necessary values are set in the ZitadelClientConfig for JWTs to be generated.
|
||||
func verifyJWTConfig(config ZitadelClientConfig) error {
|
||||
|
||||
if config.ClientID == "" {
|
||||
return fmt.Errorf("zitadel IdP configuration is incomplete, clientID is missing")
|
||||
}
|
||||
|
||||
if config.ClientSecret == "" {
|
||||
return fmt.Errorf("zitadel IdP configuration is incomplete, ClientSecret is missing")
|
||||
}
|
||||
|
||||
if config.TokenEndpoint == "" {
|
||||
return fmt.Errorf("zitadel IdP configuration is incomplete, TokenEndpoint is missing")
|
||||
}
|
||||
|
||||
if config.GrantType == "" {
|
||||
return fmt.Errorf("zitadel IdP configuration is incomplete, GrantType is missing")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewZitadelManager creates a new instance of the ZitadelManager.
|
||||
func NewZitadelManager(config ZitadelClientConfig, appMetrics telemetry.AppMetrics) (*ZitadelManager, error) {
|
||||
httpTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
@@ -146,26 +169,18 @@ func NewZitadelManager(config ZitadelClientConfig, appMetrics telemetry.AppMetri
|
||||
}
|
||||
helper := JsonParser{}
|
||||
|
||||
if config.ClientID == "" {
|
||||
return nil, fmt.Errorf("zitadel IdP configuration is incomplete, clientID is missing")
|
||||
}
|
||||
|
||||
if config.ClientSecret == "" {
|
||||
return nil, fmt.Errorf("zitadel IdP configuration is incomplete, ClientSecret is missing")
|
||||
}
|
||||
|
||||
if config.TokenEndpoint == "" {
|
||||
return nil, fmt.Errorf("zitadel IdP configuration is incomplete, TokenEndpoint is missing")
|
||||
hasPAT := config.PAT != ""
|
||||
if !hasPAT {
|
||||
jwtErr := verifyJWTConfig(config)
|
||||
if jwtErr != nil {
|
||||
return nil, jwtErr
|
||||
}
|
||||
}
|
||||
|
||||
if config.ManagementEndpoint == "" {
|
||||
return nil, fmt.Errorf("zitadel IdP configuration is incomplete, ManagementEndpoint is missing")
|
||||
}
|
||||
|
||||
if config.GrantType == "" {
|
||||
return nil, fmt.Errorf("zitadel IdP configuration is incomplete, GrantType is missing")
|
||||
}
|
||||
|
||||
credentials := &ZitadelCredentials{
|
||||
clientConfig: config,
|
||||
httpClient: httpClient,
|
||||
@@ -254,6 +269,20 @@ func (zc *ZitadelCredentials) parseRequestJWTResponse(rawBody io.ReadCloser) (JW
|
||||
return jwtToken, nil
|
||||
}
|
||||
|
||||
// generatePATToken creates a functional JWTToken instance which will pass the
|
||||
// PAT to the API directly and skip requesting a token.
|
||||
func (zc *ZitadelCredentials) generatePATToken() (JWTToken, error) {
|
||||
tok := JWTToken{
|
||||
AccessToken: zc.clientConfig.PAT,
|
||||
Scope: "openid",
|
||||
ExpiresIn: 9999,
|
||||
TokenType: "PAT",
|
||||
}
|
||||
tok.expiresInTime = time.Now().Add(time.Duration(tok.ExpiresIn) * time.Second)
|
||||
zc.jwtToken = tok
|
||||
return tok, nil
|
||||
}
|
||||
|
||||
// Authenticate retrieves access token to use the Zitadel Management API.
|
||||
func (zc *ZitadelCredentials) Authenticate(ctx context.Context) (JWTToken, error) {
|
||||
zc.mux.Lock()
|
||||
@@ -269,6 +298,10 @@ func (zc *ZitadelCredentials) Authenticate(ctx context.Context) (JWTToken, error
|
||||
return zc.jwtToken, nil
|
||||
}
|
||||
|
||||
if zc.clientConfig.PAT != "" {
|
||||
return zc.generatePATToken()
|
||||
}
|
||||
|
||||
resp, err := zc.requestJWTToken(ctx)
|
||||
if err != nil {
|
||||
return zc.jwtToken, err
|
||||
|
||||
@@ -330,10 +330,7 @@ func MigrateNewField[T any](ctx context.Context, db *gorm.DB, columnName string,
|
||||
}
|
||||
|
||||
var rows []map[string]any
|
||||
if err := tx.Table(tableName).
|
||||
Select("id", columnName).
|
||||
Where(columnName + " IS NULL OR " + columnName + " = ''").
|
||||
Find(&rows).Error; err != nil {
|
||||
if err := tx.Table(tableName).Select("id", columnName).Where(columnName + " IS NULL").Find(&rows).Error; err != nil {
|
||||
return fmt.Errorf("failed to find rows with empty %s: %w", columnName, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ func (m *managerImpl) CreateResource(ctx context.Context, userID string, resourc
|
||||
err = m.store.ExecuteInTransaction(ctx, func(transaction store.Store) error {
|
||||
_, err = transaction.GetNetworkResourceByName(ctx, store.LockingStrengthShare, resource.AccountID, resource.Name)
|
||||
if err == nil {
|
||||
return errors.New("resource already exists")
|
||||
return status.Errorf(status.InvalidArgument, "resource with name %s already exists", resource.Name)
|
||||
}
|
||||
|
||||
network, err := transaction.GetNetworkByID(ctx, store.LockingStrengthUpdate, resource.AccountID, resource.NetworkID)
|
||||
@@ -223,7 +223,7 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
|
||||
|
||||
oldResource, err := transaction.GetNetworkResourceByName(ctx, store.LockingStrengthShare, resource.AccountID, resource.Name)
|
||||
if err == nil && oldResource.ID != resource.ID {
|
||||
return errors.New("new resource name already exists")
|
||||
return status.Errorf(status.InvalidArgument, "new resource name already exists")
|
||||
}
|
||||
|
||||
oldResource, err = transaction.GetNetworkResourceByID(ctx, store.LockingStrengthShare, resource.AccountID, resource.ID)
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/geolocation"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/idp"
|
||||
"github.com/netbirdio/netbird/management/server/posture"
|
||||
"github.com/netbirdio/netbird/management/server/store"
|
||||
@@ -120,6 +122,11 @@ func (am *DefaultAccountManager) GetPeers(ctx context.Context, accountID, userID
|
||||
|
||||
// MarkPeerConnected marks peer as connected (true) or disconnected (false)
|
||||
func (am *DefaultAccountManager) MarkPeerConnected(ctx context.Context, peerPubKey string, connected bool, realIP net.IP, accountID string) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.WithContext(ctx).Debugf("MarkPeerConnected: took %v", time.Since(start))
|
||||
}()
|
||||
|
||||
var peer *nbpeer.Peer
|
||||
var settings *types.Settings
|
||||
var expired bool
|
||||
@@ -659,6 +666,11 @@ func getFreeIP(ctx context.Context, transaction store.Store, accountID string) (
|
||||
|
||||
// SyncPeer checks whether peer is eligible for receiving NetworkMap (authenticated) and returns its NetworkMap if eligible
|
||||
func (am *DefaultAccountManager) SyncPeer(ctx context.Context, sync PeerSync, accountID string) (*nbpeer.Peer, *types.NetworkMap, []*posture.Checks, error) {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
log.WithContext(ctx).Debugf("SyncPeer: took %v", time.Since(start))
|
||||
}()
|
||||
|
||||
var peer *nbpeer.Peer
|
||||
var peerNotValid bool
|
||||
var isStatusChanged bool
|
||||
|
||||
Reference in New Issue
Block a user