mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-17 15:56:39 +00:00
fix cluster logic for domains and reverse proxy
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
nbcontext "github.com/netbirdio/netbird/management/server/context"
|
||||
"github.com/netbirdio/netbird/shared/management/http/api"
|
||||
"github.com/netbirdio/netbird/shared/management/http/util"
|
||||
@@ -40,12 +39,16 @@ func domainTypeToApi(t domainType) api.ReverseProxyDomainType {
|
||||
}
|
||||
|
||||
func domainToApi(d *Domain) api.ReverseProxyDomain {
|
||||
return api.ReverseProxyDomain{
|
||||
resp := api.ReverseProxyDomain{
|
||||
Domain: d.Domain,
|
||||
Id: d.ID,
|
||||
Type: domainTypeToApi(d.Type),
|
||||
Validated: d.Validated,
|
||||
}
|
||||
if d.TargetCluster != "" {
|
||||
resp.TargetCluster = &d.TargetCluster
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func (h *handler) getAllDomains(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -82,7 +85,7 @@ func (h *handler) createCustomDomain(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
domain, err := h.manager.CreateDomain(r.Context(), userAuth.AccountId, req.Domain)
|
||||
domain, err := h.manager.CreateDomain(r.Context(), userAuth.AccountId, req.Domain, req.TargetCluster)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
return
|
||||
|
||||
@@ -19,11 +19,12 @@ const (
|
||||
)
|
||||
|
||||
type Domain struct {
|
||||
ID string `gorm:"unique;primaryKey;autoIncrement"`
|
||||
Domain string `gorm:"unique"` // Domain records must be unique, this avoids domain reuse across accounts.
|
||||
AccountID string `gorm:"index"`
|
||||
Type domainType `gorm:"-"`
|
||||
Validated bool
|
||||
ID string `gorm:"unique;primaryKey;autoIncrement"`
|
||||
Domain string `gorm:"unique"` // Domain records must be unique, this avoids domain reuse across accounts.
|
||||
AccountID string `gorm:"index"`
|
||||
TargetCluster string // The proxy cluster this domain should be validated against
|
||||
Type domainType `gorm:"-"`
|
||||
Validated bool
|
||||
}
|
||||
|
||||
type store interface {
|
||||
@@ -32,7 +33,7 @@ type store interface {
|
||||
GetCustomDomain(ctx context.Context, accountID string, domainID string) (*Domain, error)
|
||||
ListFreeDomains(ctx context.Context, accountID string) ([]string, error)
|
||||
ListCustomDomains(ctx context.Context, accountID string) ([]*Domain, error)
|
||||
CreateCustomDomain(ctx context.Context, accountID string, domainName string, validated bool) (*Domain, error)
|
||||
CreateCustomDomain(ctx context.Context, accountID string, domainName string, targetCluster string, validated bool) (*Domain, error)
|
||||
UpdateCustomDomain(ctx context.Context, accountID string, d *Domain) (*Domain, error)
|
||||
DeleteCustomDomain(ctx context.Context, accountID string, domainID string) error
|
||||
}
|
||||
@@ -85,31 +86,43 @@ func (m Manager) GetDomains(ctx context.Context, accountID string) ([]*Domain, e
|
||||
// Add custom domains.
|
||||
for _, domain := range domains {
|
||||
ret = append(ret, &Domain{
|
||||
ID: domain.ID,
|
||||
Domain: domain.Domain,
|
||||
AccountID: accountID,
|
||||
Type: TypeCustom,
|
||||
Validated: domain.Validated,
|
||||
ID: domain.ID,
|
||||
Domain: domain.Domain,
|
||||
AccountID: accountID,
|
||||
TargetCluster: domain.TargetCluster,
|
||||
Type: TypeCustom,
|
||||
Validated: domain.Validated,
|
||||
})
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (m Manager) CreateDomain(ctx context.Context, accountID, domainName string) (*Domain, error) {
|
||||
// Attempt an initial validation; however, a failure is still acceptable for creation
|
||||
// because the user may not yet have configured their DNS records, or the DNS update
|
||||
// has not yet reached the servers that are queried by the validation resolver.
|
||||
func (m Manager) CreateDomain(ctx context.Context, accountID, domainName, targetCluster string) (*Domain, error) {
|
||||
|
||||
// Verify the target cluster is in the available clusters
|
||||
allowList := m.proxyURLAllowList()
|
||||
clusterValid := false
|
||||
for _, cluster := range allowList {
|
||||
if cluster == targetCluster {
|
||||
clusterValid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !clusterValid {
|
||||
return nil, fmt.Errorf("target cluster %s is not available", targetCluster)
|
||||
}
|
||||
|
||||
// Attempt an initial validation against the specified cluster only
|
||||
var validated bool
|
||||
if m.validator.IsValid(ctx, domainName, m.proxyURLAllowList()) {
|
||||
if m.validator.IsValid(ctx, domainName, []string{targetCluster}) {
|
||||
validated = true
|
||||
}
|
||||
|
||||
d, err := m.store.CreateCustomDomain(ctx, accountID, domainName, validated)
|
||||
d, err := m.store.CreateCustomDomain(ctx, accountID, domainName, targetCluster, validated)
|
||||
if err != nil {
|
||||
return d, fmt.Errorf("create domain in store: %w", err)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -136,15 +149,25 @@ func (m Manager) ValidateDomain(accountID, domainID string) {
|
||||
return
|
||||
}
|
||||
|
||||
allowList := m.proxyURLAllowList()
|
||||
log.WithFields(log.Fields{
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
"domain": d.Domain,
|
||||
"proxyAllowList": allowList,
|
||||
}).Info("validating domain against proxy allow list")
|
||||
// Validate only against the domain's target cluster
|
||||
targetCluster := d.TargetCluster
|
||||
if targetCluster == "" {
|
||||
log.WithFields(log.Fields{
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
"domain": d.Domain,
|
||||
}).Warn("domain has no target cluster set, skipping validation")
|
||||
return
|
||||
}
|
||||
|
||||
if m.validator.IsValid(context.Background(), d.Domain, allowList) {
|
||||
log.WithFields(log.Fields{
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
"domain": d.Domain,
|
||||
"targetCluster": targetCluster,
|
||||
}).Info("validating domain against target cluster")
|
||||
|
||||
if m.validator.IsValid(context.Background(), d.Domain, []string{targetCluster}) {
|
||||
log.WithFields(log.Fields{
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
@@ -161,11 +184,11 @@ func (m Manager) ValidateDomain(accountID, domainID string) {
|
||||
}
|
||||
} else {
|
||||
log.WithFields(log.Fields{
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
"domain": d.Domain,
|
||||
"proxyAllowList": allowList,
|
||||
}).Warn("domain validation failed - CNAME does not match any connected proxy")
|
||||
"accountID": accountID,
|
||||
"domainID": domainID,
|
||||
"domain": d.Domain,
|
||||
"targetCluster": targetCluster,
|
||||
}).Warn("domain validation failed - CNAME does not match target cluster")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4845,13 +4845,14 @@ func (s *SqlStore) ListCustomDomains(ctx context.Context, accountID string) ([]*
|
||||
return domains, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) CreateCustomDomain(ctx context.Context, accountID string, domainName string, validated bool) (*domain.Domain, error) {
|
||||
func (s *SqlStore) CreateCustomDomain(ctx context.Context, accountID string, domainName string, targetCluster string, validated bool) (*domain.Domain, error) {
|
||||
newDomain := &domain.Domain{
|
||||
ID: xid.New().String(), // Generate our own ID because gorm doesn't always configure the database to handle this for us.
|
||||
Domain: domainName,
|
||||
AccountID: accountID,
|
||||
Type: domain.TypeCustom,
|
||||
Validated: validated,
|
||||
ID: xid.New().String(), // Generate our own ID because gorm doesn't always configure the database to handle this for us.
|
||||
Domain: domainName,
|
||||
AccountID: accountID,
|
||||
TargetCluster: targetCluster,
|
||||
Type: domain.TypeCustom,
|
||||
Validated: validated,
|
||||
}
|
||||
result := s.db.Create(newDomain)
|
||||
if result.Error != nil {
|
||||
|
||||
@@ -255,7 +255,7 @@ type Store interface {
|
||||
GetCustomDomain(ctx context.Context, accountID string, domainID string) (*domain.Domain, error)
|
||||
ListFreeDomains(ctx context.Context, accountID string) ([]string, error)
|
||||
ListCustomDomains(ctx context.Context, accountID string) ([]*domain.Domain, error)
|
||||
CreateCustomDomain(ctx context.Context, accountID string, domainName string, validated bool) (*domain.Domain, error)
|
||||
CreateCustomDomain(ctx context.Context, accountID string, domainName string, targetCluster string, validated bool) (*domain.Domain, error)
|
||||
UpdateCustomDomain(ctx context.Context, accountID string, d *domain.Domain) (*domain.Domain, error)
|
||||
DeleteCustomDomain(ctx context.Context, accountID string, domainID string) error
|
||||
|
||||
|
||||
@@ -3047,6 +3047,9 @@ components:
|
||||
description: Whether the domain has been validated
|
||||
type:
|
||||
$ref: '#/components/schemas/ReverseProxyDomainType'
|
||||
target_cluster:
|
||||
type: string
|
||||
description: The proxy cluster this domain is validated against (only for custom domains)
|
||||
required:
|
||||
- id
|
||||
- domain
|
||||
@@ -3058,8 +3061,12 @@ components:
|
||||
domain:
|
||||
type: string
|
||||
description: Domain name
|
||||
target_cluster:
|
||||
type: string
|
||||
description: The proxy cluster this domain should be validated against
|
||||
required:
|
||||
- domain
|
||||
- target_cluster
|
||||
InstanceStatus:
|
||||
type: object
|
||||
description: Instance status information
|
||||
|
||||
@@ -2006,6 +2006,9 @@ type ReverseProxyDomain struct {
|
||||
// Id Domain ID
|
||||
Id string `json:"id"`
|
||||
|
||||
// TargetCluster The proxy cluster this domain is validated against (only for custom domains)
|
||||
TargetCluster *string `json:"target_cluster,omitempty"`
|
||||
|
||||
// Type Type of Reverse Proxy Domain
|
||||
Type ReverseProxyDomainType `json:"type"`
|
||||
|
||||
@@ -2017,6 +2020,9 @@ type ReverseProxyDomain struct {
|
||||
type ReverseProxyDomainRequest struct {
|
||||
// Domain Domain name
|
||||
Domain string `json:"domain"`
|
||||
|
||||
// TargetCluster The proxy cluster this domain should be validated against
|
||||
TargetCluster string `json:"target_cluster"`
|
||||
}
|
||||
|
||||
// ReverseProxyDomainType Type of Reverse Proxy Domain
|
||||
|
||||
Reference in New Issue
Block a user