[management] Add custom dns zones (#4849)

This commit is contained in:
Bethuel Mmbaga
2026-01-16 10:12:05 +01:00
committed by GitHub
parent 291e640b28
commit 067c77e49e
36 changed files with 4837 additions and 63 deletions

View File

@@ -27,6 +27,8 @@ import (
"gorm.io/gorm/logger"
nbdns "github.com/netbirdio/netbird/dns"
"github.com/netbirdio/netbird/management/internals/modules/zones"
"github.com/netbirdio/netbird/management/internals/modules/zones/records"
resourceTypes "github.com/netbirdio/netbird/management/server/networks/resources/types"
routerTypes "github.com/netbirdio/netbird/management/server/networks/routers/types"
networkTypes "github.com/netbirdio/netbird/management/server/networks/types"
@@ -123,6 +125,7 @@ func NewSqlStore(ctx context.Context, db *gorm.DB, storeEngine types.Engine, met
&types.Account{}, &types.Policy{}, &types.PolicyRule{}, &route.Route{}, &nbdns.NameServerGroup{},
&installation{}, &types.ExtraSettings{}, &posture.Checks{}, &nbpeer.NetworkAddress{},
&networkTypes.Network{}, &routerTypes.NetworkRouter{}, &resourceTypes.NetworkResource{}, &types.AccountOnboarding{},
&zones.Zone{}, &records.Record{},
)
if err != nil {
return nil, fmt.Errorf("auto migratePreAuto: %w", err)
@@ -4179,3 +4182,184 @@ func (s *SqlStore) GetUserIDByPeerKey(ctx context.Context, lockStrength LockingS
return userID, nil
}
func (s *SqlStore) CreateZone(ctx context.Context, zone *zones.Zone) error {
result := s.db.Create(zone)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to create zone to store: %v", result.Error)
return status.Errorf(status.Internal, "failed to create zone to store")
}
return nil
}
func (s *SqlStore) UpdateZone(ctx context.Context, zone *zones.Zone) error {
result := s.db.Select("*").Save(zone)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to update zone to store: %v", result.Error)
return status.Errorf(status.Internal, "failed to update zone to store")
}
return nil
}
func (s *SqlStore) DeleteZone(ctx context.Context, accountID, zoneID string) error {
result := s.db.Delete(&zones.Zone{}, accountAndIDQueryCondition, accountID, zoneID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to delete zone from store: %v", result.Error)
return status.Errorf(status.Internal, "failed to delete zone from store")
}
if result.RowsAffected == 0 {
return status.NewZoneNotFoundError(zoneID)
}
return nil
}
func (s *SqlStore) GetZoneByID(ctx context.Context, lockStrength LockingStrength, accountID, zoneID string) (*zones.Zone, error) {
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
}
var zone *zones.Zone
result := tx.Preload("Records").Take(&zone, accountAndIDQueryCondition, accountID, zoneID)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, status.NewZoneNotFoundError(zoneID)
}
log.WithContext(ctx).Errorf("failed to get zone from store: %v", result.Error)
return nil, status.Errorf(status.Internal, "failed to get zone from store")
}
return zone, nil
}
func (s *SqlStore) GetZoneByDomain(ctx context.Context, accountID, domain string) (*zones.Zone, error) {
var zone *zones.Zone
result := s.db.Where("account_id = ? AND domain = ?", accountID, domain).First(&zone)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, status.NewZoneNotFoundError(domain)
}
log.WithContext(ctx).Errorf("failed to get zone by domain from store: %v", result.Error)
return nil, status.Errorf(status.Internal, "failed to get zone by domain from store")
}
return zone, nil
}
func (s *SqlStore) GetAccountZones(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*zones.Zone, error) {
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
}
var zones []*zones.Zone
result := tx.Preload("Records").Find(&zones, accountIDCondition, accountID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to get zones from the store: %s", result.Error)
return nil, status.Errorf(status.Internal, "failed to get zones from store")
}
return zones, nil
}
func (s *SqlStore) CreateDNSRecord(ctx context.Context, record *records.Record) error {
result := s.db.Create(record)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to create dns record to store: %v", result.Error)
return status.Errorf(status.Internal, "failed to create dns record to store")
}
return nil
}
func (s *SqlStore) UpdateDNSRecord(ctx context.Context, record *records.Record) error {
result := s.db.Select("*").Save(record)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to update dns record to store: %v", result.Error)
return status.Errorf(status.Internal, "failed to update dns record to store")
}
return nil
}
func (s *SqlStore) DeleteDNSRecord(ctx context.Context, accountID, zoneID, recordID string) error {
result := s.db.Delete(&records.Record{}, "account_id = ? AND zone_id = ? AND id = ?", accountID, zoneID, recordID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to delete dns record from store: %v", result.Error)
return status.Errorf(status.Internal, "failed to delete dns record from store")
}
if result.RowsAffected == 0 {
return status.NewDNSRecordNotFoundError(recordID)
}
return nil
}
func (s *SqlStore) GetDNSRecordByID(ctx context.Context, lockStrength LockingStrength, accountID, zoneID, recordID string) (*records.Record, error) {
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
}
var record *records.Record
result := tx.Where("account_id = ? AND zone_id = ? AND id = ?", accountID, zoneID, recordID).Take(&record)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, status.NewDNSRecordNotFoundError(recordID)
}
log.WithContext(ctx).Errorf("failed to get dns record from store: %v", result.Error)
return nil, status.Errorf(status.Internal, "failed to get dns record from store")
}
return record, nil
}
func (s *SqlStore) GetZoneDNSRecords(ctx context.Context, lockStrength LockingStrength, accountID, zoneID string) ([]*records.Record, error) {
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
}
var recordsList []*records.Record
result := tx.Where("account_id = ? AND zone_id = ?", accountID, zoneID).Find(&recordsList)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to get zone dns records from the store: %s", result.Error)
return nil, status.Errorf(status.Internal, "failed to get zone dns records from store")
}
return recordsList, nil
}
func (s *SqlStore) GetZoneDNSRecordsByName(ctx context.Context, lockStrength LockingStrength, accountID, zoneID, name string) ([]*records.Record, error) {
tx := s.db
if lockStrength != LockingStrengthNone {
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
}
var recordsList []*records.Record
result := tx.Where("account_id = ? AND zone_id = ? AND name = ?", accountID, zoneID, name).Find(&recordsList)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to get zone dns records by name from the store: %s", result.Error)
return nil, status.Errorf(status.Internal, "failed to get zone dns records by name from store")
}
return recordsList, nil
}
func (s *SqlStore) DeleteZoneDNSRecords(ctx context.Context, accountID, zoneID string) error {
result := s.db.Delete(&records.Record{}, "account_id = ? AND zone_id = ?", accountID, zoneID)
if result.Error != nil {
log.WithContext(ctx).Errorf("failed to delete zone dns records from store: %v", result.Error)
return status.Errorf(status.Internal, "failed to delete zone dns records from store")
}
return nil
}