From 0b29c6ed1a9df8e7ad5ffca4449514f23f188b76 Mon Sep 17 00:00:00 2001 From: Dmitri Dolguikh Date: Mon, 3 Aug 2026 17:29:09 +0200 Subject: [PATCH] adding buildPrivateServiceCandidates Signed-off-by: Dmitri Dolguikh --- .../internals/network_map_db/pgsql/domain.go | 38 ++++++++++++ .../network_map_db/pgsql/group_test.go | 26 ++++++++ .../network_map_db/pgsql/network_map_data.go | 61 ++++++++++++++++++- .../internals/network_map_db/pgsql/peer.go | 8 +-- .../internals/network_map_db/pgsql/service.go | 41 +++++++++++++ .../internals/network_map_db/pgsql/user.go | 12 +--- 6 files changed, 172 insertions(+), 14 deletions(-) create mode 100644 management/internals/network_map_db/pgsql/domain.go create mode 100644 management/internals/network_map_db/pgsql/service.go diff --git a/management/internals/network_map_db/pgsql/domain.go b/management/internals/network_map_db/pgsql/domain.go new file mode 100644 index 000000000..6a2e99778 --- /dev/null +++ b/management/internals/network_map_db/pgsql/domain.go @@ -0,0 +1,38 @@ +package networkmap_pgsql + +import ( + "context" + "database/sql" + + "github.com/jackc/pgx/v5" +) + +const ( + GetDomainsQuery = ` + select domain, target_cluster + from domains + where account_id=$1 + ` +) + +func (pg *PgStore) GetDomains(ctx context.Context, accountId string) ([]domain, error) { + c, err := pg.Pool.Acquire(ctx) + if err != nil { + return nil, err + } + return GetDomainsViaPgxConnection(ctx, c.Conn(), accountId) +} + +func GetDomainsViaPgxConnection(ctx context.Context, conn *pgx.Conn, accountId string) ([]domain, error) { + rows, err := conn.Query(ctx, GetDomainsQuery, accountId) + if err != nil { + return nil, err + } + + return pgx.CollectRows(rows, pgx.RowToStructByName[domain]) +} + +type domain struct { + Domain sql.NullString + TargetCluster sql.NullString +} diff --git a/management/internals/network_map_db/pgsql/group_test.go b/management/internals/network_map_db/pgsql/group_test.go index ee4e2be87..7154b5e6e 100644 --- a/management/internals/network_map_db/pgsql/group_test.go +++ b/management/internals/network_map_db/pgsql/group_test.go @@ -281,3 +281,29 @@ func TestGetDnsSettings(t *testing.T) { assert.NoError(t, err) assert.NotEmpty(t, set.DisabledManagementGroups) } + +func TestGetDomains(t *testing.T) { + ctx := context.TODO() + + s, err := NewPostgresqlStore(ctx, "postgresql://root:netbird@localhost:5432/netbird") + assert.NoError(t, err) + // err = loadSQL(ctx, s.pool, initDb) + //assert.NoError(t, err) + + domains, err := s.GetDomains(ctx, "d8f79r2fadhs73c6uc0g") //"ckd7ee2fic3c73dtendg") + assert.NoError(t, err) + assert.NotEmpty(t, domains) +} + +func TestGetServices(t *testing.T) { + ctx := context.TODO() + + s, err := NewPostgresqlStore(ctx, "postgresql://root:netbird@localhost:5432/netbird") + assert.NoError(t, err) + // err = loadSQL(ctx, s.pool, initDb) + //assert.NoError(t, err) + + svcs, err := s.GetPrivateServices(ctx, "d7jlh32fadhs73btp9u0") //"d6snsejl0ubs738s3f40") //"ckd7ee2fic3c73dtendg") + assert.NoError(t, err) + assert.NotEmpty(t, svcs) +} diff --git a/management/internals/network_map_db/pgsql/network_map_data.go b/management/internals/network_map_db/pgsql/network_map_data.go index 60dc6128d..a94a52623 100644 --- a/management/internals/network_map_db/pgsql/network_map_data.go +++ b/management/internals/network_map_db/pgsql/network_map_data.go @@ -2,6 +2,7 @@ package networkmap_pgsql import ( "context" + "strings" "github.com/jackc/pgx/v5" "github.com/netbirdio/netbird/shared/management/networkmap" @@ -42,7 +43,7 @@ func (pg *PgStore) GetNetworkMapData(ctx context.Context, accountId string) (*ne if err != nil { return rollbackAndReturnError(ctx, tx, err) } - peers, _, err := GetPeersViaPgxConnection(ctx, tx.Conn(), accountId) + peers, proxyPeers, err := GetPeersViaPgxConnection(ctx, tx.Conn(), accountId) if err != nil { return rollbackAndReturnError(ctx, tx, err) } @@ -70,6 +71,14 @@ func (pg *PgStore) GetNetworkMapData(ctx context.Context, accountId string) (*ne if err != nil { return rollbackAndReturnError(ctx, tx, err) } + // domains, err := GetDomainsViaPgxConnection(ctx, tx.Conn(), accountId) + // if err != nil { + // return rollbackAndReturnError(ctx, tx, err) + // } + services, err := GetPrivateServicesViaPgxConnection(ctx, tx.Conn(), accountId) + if err != nil { + return rollbackAndReturnError(ctx, tx, err) + } resourcePolicies := make(map[string][]*nmdata.Policy) for _, resource := range networkResources { @@ -145,3 +154,53 @@ func toSliceOfPtrs[T any](all []T) []*T { } return toret } + +func serviceDomainZone(svc service, ds []domain) string { + if domainFromSuffix(svc.Domain.String, svc.ProxyCluster.String) { + return svc.ProxyCluster.String + } + + var zoneName string + for _, domain := range ds { + if domain.TargetCluster.String != svc.ProxyCluster.String { + continue + } + if domainFromSuffix(svc.Domain.String, domain.Domain.String) && len(domain.Domain.String) > len(zoneName) { + zoneName = domain.Domain.String + } + } + + return zoneName +} + +func domainFromSuffix(domain, suffix string) bool { + if suffix == "" { + return false + } + return domain == suffix || strings.HasSuffix(domain, "."+suffix) +} + +func buildPrivateServiceCandidates(svcs []service, domains []domain, proxyPeersByCluster map[string][]*nmdata.Peer) []networkmap.PrivateServiceCandidate { + var out []networkmap.PrivateServiceCandidate + + if len(proxyPeersByCluster) == 0 { + return out + } + + for _, svc := range svcs { + if len(svc.AccessGroups) == 0 { + continue + } + + domainZone := serviceDomainZone(svc, domains) + if domainZone == "" { + continue + } + + for _, proxyPeer := range proxyPeersByCluster[svc.ProxyCluster.String] { + if !proxyPeer.IP.IsValid() { + continue + } + } + } +} diff --git a/management/internals/network_map_db/pgsql/peer.go b/management/internals/network_map_db/pgsql/peer.go index 7d62df4ba..b11c3ef7b 100644 --- a/management/internals/network_map_db/pgsql/peer.go +++ b/management/internals/network_map_db/pgsql/peer.go @@ -22,7 +22,7 @@ const ( ` ) -func (pg *PgStore) GetPeers(ctx context.Context, accountId string) ([]nmdata.Peer, map[string]*nmdata.Peer, error) { +func (pg *PgStore) GetPeers(ctx context.Context, accountId string) ([]nmdata.Peer, map[string][]*nmdata.Peer, error) { c, err := pg.Pool.Acquire(ctx) if err != nil { return nil, nil, err @@ -30,7 +30,7 @@ func (pg *PgStore) GetPeers(ctx context.Context, accountId string) ([]nmdata.Pee return GetPeersViaPgxConnection(ctx, c.Conn(), accountId) } -func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId string) ([]nmdata.Peer, map[string]*nmdata.Peer, error) { +func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId string) ([]nmdata.Peer, map[string][]*nmdata.Peer, error) { rows, err := con.Query(ctx, GetPeersQuery, accountId) if err != nil { return nil, nil, err @@ -42,7 +42,7 @@ func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId stri } toret := make([]nmdata.Peer, 0, len(peers)) - clusterToPeerIdx := make(map[string]*nmdata.Peer) + clusterToPeerIdx := make(map[string][]*nmdata.Peer) for _, p := range peers { dp := nmdata.Peer{} err := networkmapdb.FromSqlTypesToSharedTypes( @@ -55,7 +55,7 @@ func GetPeersViaPgxConnection(ctx context.Context, con *pgx.Conn, accountId stri dp.ProxyMeta.Embedded = p.ProxyMetaEmbedded.Bool } if dp.ProxyMeta.Embedded { - clusterToPeerIdx[p.ProxyMetaCluster.String] = &dp + clusterToPeerIdx[p.ProxyMetaCluster.String] = append(clusterToPeerIdx[p.ProxyMetaCluster.String], &dp) } if p.MetaWtVersion.Valid { dp.Meta.WtVersion = p.MetaWtVersion.String diff --git a/management/internals/network_map_db/pgsql/service.go b/management/internals/network_map_db/pgsql/service.go new file mode 100644 index 000000000..d4ad31219 --- /dev/null +++ b/management/internals/network_map_db/pgsql/service.go @@ -0,0 +1,41 @@ +package networkmap_pgsql + +import ( + "context" + "database/sql" + + "github.com/jackc/pgx/v5" +) + +const ( + GetServicesQuery = ` + select enabled, private, array (select json_array_elements_text(access_groups::json)) as access_groups, proxy_cluster, domain + from services + where account_id=$1 + ` +) + +func (pg *PgStore) GetPrivateServices(ctx context.Context, accountId string) ([]service, error) { + c, err := pg.Pool.Acquire(ctx) + if err != nil { + return nil, err + } + return GetPrivateServicesViaPgxConnection(ctx, c.Conn(), accountId) +} + +func GetPrivateServicesViaPgxConnection(ctx context.Context, conn *pgx.Conn, accountId string) ([]service, error) { + rows, err := conn.Query(ctx, GetServicesQuery, accountId) + if err != nil { + return nil, err + } + + return pgx.CollectRows(rows, pgx.RowToStructByName[service]) +} + +type service struct { + Enabled sql.NullBool + Private sql.NullBool + AccessGroups []string + ProxyCluster sql.NullString + Domain sql.NullString +} diff --git a/management/internals/network_map_db/pgsql/user.go b/management/internals/network_map_db/pgsql/user.go index 7f6d2ec9f..ede46ec96 100644 --- a/management/internals/network_map_db/pgsql/user.go +++ b/management/internals/network_map_db/pgsql/user.go @@ -2,14 +2,13 @@ package networkmap_pgsql import ( "context" - "encoding/json" "github.com/jackc/pgx/v5" ) const ( GetAllowedUserIdsQuery = ` - select id, auto_groups + select id, array (select json_array_elements_text(auto_groups::json)) as auto_groups from users where account_id=$1 and not blocked and not is_service_user ` @@ -38,12 +37,7 @@ func GetAllowedUsersViaPgxConnection(ctx context.Context, con *pgx.Conn, account groupIdToUserIds := make(map[string][]string) for _, user := range users { userIdIdx[user.ID] = struct{}{} - - var groupIds []string - if err := json.Unmarshal(user.AutoGroups, &groupIds); err != nil { - return nil, nil, err - } - for _, groupId := range groupIds { + for _, groupId := range user.AutoGroups { groupIdToUserIds[groupId] = append(groupIdToUserIds[groupId], user.ID) } } @@ -53,5 +47,5 @@ func GetAllowedUsersViaPgxConnection(ctx context.Context, con *pgx.Conn, account type user struct { ID string - AutoGroups json.RawMessage + AutoGroups []string }