add permissions validation to domain manager

This commit is contained in:
pascal
2026-02-12 14:31:23 +01:00
parent 6f2f0f9ae4
commit ee2ae45653
9 changed files with 144 additions and 82 deletions

View File

@@ -0,0 +1,17 @@
package domain
type DomainType string
const (
TypeFree DomainType = "free"
TypeCustom DomainType = "custom"
)
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"`
TargetCluster string // The proxy cluster this domain should be validated against
Type DomainType `gorm:"-"`
Validated bool
}

View File

@@ -0,0 +1,12 @@
package domain
import (
"context"
)
type Manager interface {
GetDomains(ctx context.Context, accountID, userID string) ([]*Domain, error)
CreateDomain(ctx context.Context, accountID, userID, domainName, targetCluster string) (*Domain, error)
DeleteDomain(ctx context.Context, accountID, userID, domainID string) error
ValidateDomain(ctx context.Context, accountID, userID, domainID string)
}

View File

@@ -1,10 +1,12 @@
package domain package manager
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain"
nbcontext "github.com/netbirdio/netbird/management/server/context" nbcontext "github.com/netbirdio/netbird/management/server/context"
"github.com/netbirdio/netbird/shared/management/http/api" "github.com/netbirdio/netbird/shared/management/http/api"
"github.com/netbirdio/netbird/shared/management/http/util" "github.com/netbirdio/netbird/shared/management/http/util"
@@ -26,11 +28,11 @@ func RegisterEndpoints(router *mux.Router, manager Manager) {
router.HandleFunc("/domains/{domainId}/validate", h.triggerCustomDomainValidation).Methods("GET", "OPTIONS") router.HandleFunc("/domains/{domainId}/validate", h.triggerCustomDomainValidation).Methods("GET", "OPTIONS")
} }
func domainTypeToApi(t domainType) api.ReverseProxyDomainType { func domainTypeToApi(t domain.DomainType) api.ReverseProxyDomainType {
switch t { switch t {
case TypeCustom: case domain.TypeCustom:
return api.ReverseProxyDomainTypeCustom return api.ReverseProxyDomainTypeCustom
case TypeFree: case domain.TypeFree:
return api.ReverseProxyDomainTypeFree return api.ReverseProxyDomainTypeFree
} }
// By default return as a "free" domain as that is more restrictive. // By default return as a "free" domain as that is more restrictive.
@@ -38,7 +40,7 @@ func domainTypeToApi(t domainType) api.ReverseProxyDomainType {
return api.ReverseProxyDomainTypeFree return api.ReverseProxyDomainTypeFree
} }
func domainToApi(d *Domain) api.ReverseProxyDomain { func domainToApi(d *domain.Domain) api.ReverseProxyDomain {
resp := api.ReverseProxyDomain{ resp := api.ReverseProxyDomain{
Domain: d.Domain, Domain: d.Domain,
Id: d.ID, Id: d.ID,
@@ -58,7 +60,7 @@ func (h *handler) getAllDomains(w http.ResponseWriter, r *http.Request) {
return return
} }
domains, err := h.manager.GetDomains(r.Context(), userAuth.AccountId) domains, err := h.manager.GetDomains(r.Context(), userAuth.AccountId, userAuth.UserId)
if err != nil { if err != nil {
util.WriteError(r.Context(), err, w) util.WriteError(r.Context(), err, w)
return return
@@ -85,7 +87,7 @@ func (h *handler) createCustomDomain(w http.ResponseWriter, r *http.Request) {
return return
} }
domain, err := h.manager.CreateDomain(r.Context(), userAuth.AccountId, req.Domain, req.TargetCluster) domain, err := h.manager.CreateDomain(r.Context(), userAuth.AccountId, userAuth.UserId, req.Domain, req.TargetCluster)
if err != nil { if err != nil {
util.WriteError(r.Context(), err, w) util.WriteError(r.Context(), err, w)
return return
@@ -107,7 +109,7 @@ func (h *handler) deleteCustomDomain(w http.ResponseWriter, r *http.Request) {
return return
} }
if err := h.manager.DeleteDomain(r.Context(), userAuth.AccountId, domainID); err != nil { if err := h.manager.DeleteDomain(r.Context(), userAuth.AccountId, userAuth.UserId, domainID); err != nil {
util.WriteError(r.Context(), err, w) util.WriteError(r.Context(), err, w)
return return
} }
@@ -128,7 +130,7 @@ func (h *handler) triggerCustomDomainValidation(w http.ResponseWriter, r *http.R
return return
} }
go h.manager.ValidateDomain(userAuth.AccountId, domainID) go h.manager.ValidateDomain(r.Context(), userAuth.AccountId, userAuth.UserId, domainID)
w.WriteHeader(http.StatusAccepted) w.WriteHeader(http.StatusAccepted)
} }

View File

@@ -1,4 +1,4 @@
package domain package manager
import ( import (
"context" "context"
@@ -7,34 +7,24 @@ import (
"net/url" "net/url"
"strings" "strings"
"github.com/netbirdio/netbird/management/server/types"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain"
"github.com/netbirdio/netbird/management/server/permissions"
"github.com/netbirdio/netbird/management/server/permissions/modules"
"github.com/netbirdio/netbird/management/server/permissions/operations"
"github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/shared/management/status"
) )
type domainType string
const (
TypeFree domainType = "free"
TypeCustom domainType = "custom"
)
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"`
TargetCluster string // The proxy cluster this domain should be validated against
Type domainType `gorm:"-"`
Validated bool
}
type store interface { type store interface {
GetAccount(ctx context.Context, accountID string) (*types.Account, error) GetAccount(ctx context.Context, accountID string) (*types.Account, error)
GetCustomDomain(ctx context.Context, accountID string, domainID string) (*Domain, error) GetCustomDomain(ctx context.Context, accountID string, domainID string) (*domain.Domain, error)
ListFreeDomains(ctx context.Context, accountID string) ([]string, error) ListFreeDomains(ctx context.Context, accountID string) ([]string, error)
ListCustomDomains(ctx context.Context, accountID string) ([]*Domain, error) ListCustomDomains(ctx context.Context, accountID string) ([]*domain.Domain, error)
CreateCustomDomain(ctx context.Context, accountID string, domainName string, targetCluster string, validated bool) (*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, error) UpdateCustomDomain(ctx context.Context, accountID string, d *domain.Domain) (*domain.Domain, error)
DeleteCustomDomain(ctx context.Context, accountID string, domainID string) error DeleteCustomDomain(ctx context.Context, accountID string, domainID string) error
} }
@@ -43,28 +33,38 @@ type proxyURLProvider interface {
} }
type Manager struct { type Manager struct {
store store store store
validator Validator validator domain.Validator
proxyURLProvider proxyURLProvider proxyURLProvider proxyURLProvider
permissionsManager permissions.Manager
} }
func NewManager(store store, proxyURLProvider proxyURLProvider) Manager { func NewManager(store store, proxyURLProvider proxyURLProvider, permissionsManager permissions.Manager) Manager {
return Manager{ return Manager{
store: store, store: store,
proxyURLProvider: proxyURLProvider, proxyURLProvider: proxyURLProvider,
validator: Validator{ validator: domain.Validator{
resolver: net.DefaultResolver, Resolver: net.DefaultResolver,
}, },
permissionsManager: permissionsManager,
} }
} }
func (m Manager) GetDomains(ctx context.Context, accountID string) ([]*Domain, error) { func (m Manager) GetDomains(ctx context.Context, accountID, userID string) ([]*domain.Domain, error) {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Read)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
domains, err := m.store.ListCustomDomains(ctx, accountID) domains, err := m.store.ListCustomDomains(ctx, accountID)
if err != nil { if err != nil {
return nil, fmt.Errorf("list custom domains: %w", err) return nil, fmt.Errorf("list custom domains: %w", err)
} }
var ret []*Domain var ret []*domain.Domain
// Add connected proxy clusters as free domains. // Add connected proxy clusters as free domains.
// The cluster address itself is the free domain base (e.g., "eu.proxy.netbird.io"). // The cluster address itself is the free domain base (e.g., "eu.proxy.netbird.io").
@@ -75,30 +75,37 @@ func (m Manager) GetDomains(ctx context.Context, accountID string) ([]*Domain, e
}).Debug("getting domains with proxy allow list") }).Debug("getting domains with proxy allow list")
for _, cluster := range allowList { for _, cluster := range allowList {
ret = append(ret, &Domain{ ret = append(ret, &domain.Domain{
Domain: cluster, Domain: cluster,
AccountID: accountID, AccountID: accountID,
Type: TypeFree, Type: domain.TypeFree,
Validated: true, Validated: true,
}) })
} }
// Add custom domains. // Add custom domains.
for _, domain := range domains { for _, d := range domains {
ret = append(ret, &Domain{ ret = append(ret, &domain.Domain{
ID: domain.ID, ID: d.ID,
Domain: domain.Domain, Domain: d.Domain,
AccountID: accountID, AccountID: accountID,
TargetCluster: domain.TargetCluster, TargetCluster: d.TargetCluster,
Type: TypeCustom, Type: domain.TypeCustom,
Validated: domain.Validated, Validated: d.Validated,
}) })
} }
return ret, nil return ret, nil
} }
func (m Manager) CreateDomain(ctx context.Context, accountID, domainName, targetCluster string) (*Domain, error) { func (m Manager) CreateDomain(ctx context.Context, accountID, userID, domainName, targetCluster string) (*domain.Domain, error) {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Create)
if err != nil {
return nil, status.NewPermissionValidationError(err)
}
if !ok {
return nil, status.NewPermissionDeniedError()
}
// Verify the target cluster is in the available clusters // Verify the target cluster is in the available clusters
allowList := m.proxyURLAllowList() allowList := m.proxyURLAllowList()
@@ -126,7 +133,15 @@ func (m Manager) CreateDomain(ctx context.Context, accountID, domainName, target
return d, nil return d, nil
} }
func (m Manager) DeleteDomain(ctx context.Context, accountID, domainID string) error { func (m Manager) DeleteDomain(ctx context.Context, accountID, userID, domainID string) error {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Delete)
if err != nil {
return status.NewPermissionValidationError(err)
}
if !ok {
return status.NewPermissionDeniedError()
}
if err := m.store.DeleteCustomDomain(ctx, accountID, domainID); err != nil { if err := m.store.DeleteCustomDomain(ctx, accountID, domainID); err != nil {
// TODO: check for "no records" type error. Because that is a success condition. // TODO: check for "no records" type error. Because that is a success condition.
return fmt.Errorf("delete domain from store: %w", err) return fmt.Errorf("delete domain from store: %w", err)
@@ -134,7 +149,22 @@ func (m Manager) DeleteDomain(ctx context.Context, accountID, domainID string) e
return nil return nil
} }
func (m Manager) ValidateDomain(accountID, domainID string) { func (m Manager) ValidateDomain(ctx context.Context, accountID, userID, domainID string) {
ok, err := m.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Services, operations.Create)
if err != nil {
log.WithFields(log.Fields{
"accountID": accountID,
"domainID": domainID,
}).WithError(err).Error("validate domain")
return
}
if !ok {
log.WithFields(log.Fields{
"accountID": accountID,
"domainID": domainID,
}).WithError(err).Error("validate domain")
}
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"accountID": accountID, "accountID": accountID,
"domainID": domainID, "domainID": domainID,
@@ -260,3 +290,15 @@ func (m Manager) DeriveClusterFromDomain(ctx context.Context, domain string) (st
return "", fmt.Errorf("domain %s does not match any available proxy cluster", domain) return "", fmt.Errorf("domain %s does not match any available proxy cluster", domain)
} }
// ExtractClusterFromFreeDomain extracts the cluster address from a free domain.
// Free domains have the format: <name>.<nonce>.<cluster> (e.g., myapp.abc123.eu.proxy.netbird.io)
// It matches the domain suffix against available clusters and returns the matching cluster.
func ExtractClusterFromFreeDomain(domain string, availableClusters []string) (string, bool) {
for _, cluster := range availableClusters {
if strings.HasSuffix(domain, "."+cluster) {
return cluster, true
}
}
return "", false
}

View File

@@ -13,15 +13,15 @@ type resolver interface {
} }
type Validator struct { type Validator struct {
resolver resolver Resolver resolver
} }
// NewValidator initializes a validator with a specific DNS resolver. // NewValidator initializes a validator with a specific DNS Resolver.
// If a Validator is used without specifying a resolver, then it will // If a Validator is used without specifying a Resolver, then it will
// use the net.DefaultResolver. // use the net.DefaultResolver.
func NewValidator(resolver resolver) *Validator { func NewValidator(resolver resolver) *Validator {
return &Validator{ return &Validator{
resolver: resolver, Resolver: resolver,
} }
} }
@@ -39,8 +39,8 @@ func (v *Validator) IsValid(ctx context.Context, domain string, accept []string)
// ValidateWithCluster validates a custom domain and returns the matched cluster address. // ValidateWithCluster validates a custom domain and returns the matched cluster address.
// Returns the cluster address and true if valid, or empty string and false if invalid. // Returns the cluster address and true if valid, or empty string and false if invalid.
func (v *Validator) ValidateWithCluster(ctx context.Context, domain string, accept []string) (string, bool) { func (v *Validator) ValidateWithCluster(ctx context.Context, domain string, accept []string) (string, bool) {
if v.resolver == nil { if v.Resolver == nil {
v.resolver = net.DefaultResolver v.Resolver = net.DefaultResolver
} }
lookupDomain := "validation." + domain lookupDomain := "validation." + domain
@@ -50,7 +50,7 @@ func (v *Validator) ValidateWithCluster(ctx context.Context, domain string, acce
"acceptList": accept, "acceptList": accept,
}).Debug("looking up CNAME for domain validation") }).Debug("looking up CNAME for domain validation")
cname, err := v.resolver.LookupCNAME(ctx, lookupDomain) cname, err := v.Resolver.LookupCNAME(ctx, lookupDomain)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"domain": domain, "domain": domain,
@@ -86,15 +86,3 @@ func (v *Validator) ValidateWithCluster(ctx context.Context, domain string, acce
}).Warn("domain CNAME does not match any accepted cluster") }).Warn("domain CNAME does not match any accepted cluster")
return "", false return "", false
} }
// ExtractClusterFromFreeDomain extracts the cluster address from a free domain.
// Free domains have the format: <name>.<nonce>.<cluster> (e.g., myapp.abc123.eu.proxy.netbird.io)
// It matches the domain suffix against available clusters and returns the matching cluster.
func ExtractClusterFromFreeDomain(domain string, availableClusters []string) (string, bool) {
for _, cluster := range availableClusters {
if strings.HasSuffix(domain, "."+cluster) {
return cluster, true
}
}
return "", false
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs"
accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager" accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" domainmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain/manager"
nbcontext "github.com/netbirdio/netbird/management/server/context" nbcontext "github.com/netbirdio/netbird/management/server/context"
"github.com/netbirdio/netbird/shared/management/http/api" "github.com/netbirdio/netbird/shared/management/http/api"
"github.com/netbirdio/netbird/shared/management/http/util" "github.com/netbirdio/netbird/shared/management/http/util"
@@ -21,13 +21,13 @@ type handler struct {
} }
// RegisterEndpoints registers all service HTTP endpoints. // RegisterEndpoints registers all service HTTP endpoints.
func RegisterEndpoints(manager reverseproxy.Manager, domainManager domain.Manager, accessLogsManager accesslogs.Manager, router *mux.Router) { func RegisterEndpoints(manager reverseproxy.Manager, domainManager domainmanager.Manager, accessLogsManager accesslogs.Manager, router *mux.Router) {
h := &handler{ h := &handler{
manager: manager, manager: manager,
} }
domainRouter := router.PathPrefix("/reverse-proxies").Subrouter() domainRouter := router.PathPrefix("/reverse-proxies").Subrouter()
domain.RegisterEndpoints(domainRouter, domainManager) domainmanager.RegisterEndpoints(domainRouter, domainManager)
accesslogsmanager.RegisterEndpoints(router, accessLogsManager) accesslogsmanager.RegisterEndpoints(router, accessLogsManager)

View File

@@ -9,7 +9,7 @@ import (
"github.com/netbirdio/management-integrations/integrations" "github.com/netbirdio/management-integrations/integrations"
"github.com/netbirdio/netbird/management/internals/modules/peers" "github.com/netbirdio/netbird/management/internals/modules/peers"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain/manager"
nbreverseproxy "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager" nbreverseproxy "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager"
"github.com/netbirdio/netbird/management/internals/modules/zones" "github.com/netbirdio/netbird/management/internals/modules/zones"
zonesManager "github.com/netbirdio/netbird/management/internals/modules/zones/manager" zonesManager "github.com/netbirdio/netbird/management/internals/modules/zones/manager"
@@ -196,9 +196,9 @@ func (s *BaseServer) ReverseProxyManager() reverseproxy.Manager {
}) })
} }
func (s *BaseServer) ReverseProxyDomainManager() *domain.Manager { func (s *BaseServer) ReverseProxyDomainManager() *manager.Manager {
return Create(s, func() *domain.Manager { return Create(s, func() *manager.Manager {
m := domain.NewManager(s.Store(), s.ReverseProxyGRPCServer()) m := manager.NewManager(s.Store(), s.ReverseProxyGRPCServer(), s.PermissionsManager())
return &m return &m
}) })
} }

View File

@@ -9,13 +9,14 @@ import (
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/netbirdio/netbird/management/server/types"
"github.com/rs/cors" "github.com/rs/cors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain/manager"
"github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain"
reverseproxymanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager" reverseproxymanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager"
nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc" nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
idpmanager "github.com/netbirdio/netbird/management/server/idp" idpmanager "github.com/netbirdio/netbird/management/server/idp"
@@ -67,7 +68,7 @@ const (
) )
// NewAPIHandler creates the Management service HTTP API handler registering all the available endpoints. // NewAPIHandler creates the Management service HTTP API handler registering all the available endpoints.
func NewAPIHandler(ctx context.Context, accountManager account.Manager, networksManager nbnetworks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager nbgroups.Manager, LocationManager geolocation.Geolocation, authManager auth.Manager, appMetrics telemetry.AppMetrics, integratedValidator integrated_validator.IntegratedValidator, proxyController port_forwarding.Controller, permissionsManager permissions.Manager, peersManager nbpeers.Manager, settingsManager settings.Manager, zManager zones.Manager, rManager records.Manager, networkMapController network_map.Controller, idpManager idpmanager.Manager, reverseProxyManager reverseproxy.Manager, reverseProxyDomainManager *domain.Manager, reverseProxyAccessLogsManager accesslogs.Manager, proxyGRPCServer *nbgrpc.ProxyServiceServer) (http.Handler, error) { func NewAPIHandler(ctx context.Context, accountManager account.Manager, networksManager nbnetworks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager nbgroups.Manager, LocationManager geolocation.Geolocation, authManager auth.Manager, appMetrics telemetry.AppMetrics, integratedValidator integrated_validator.IntegratedValidator, proxyController port_forwarding.Controller, permissionsManager permissions.Manager, peersManager nbpeers.Manager, settingsManager settings.Manager, zManager zones.Manager, rManager records.Manager, networkMapController network_map.Controller, idpManager idpmanager.Manager, reverseProxyManager reverseproxy.Manager, reverseProxyDomainManager *manager.Manager, reverseProxyAccessLogsManager accesslogs.Manager, proxyGRPCServer *nbgrpc.ProxyServiceServer) (http.Handler, error) {
// Register bypass paths for unauthenticated endpoints // Register bypass paths for unauthenticated endpoints
if err := bypass.AddBypassPath("/api/instance"); err != nil { if err := bypass.AddBypassPath("/api/instance"); err != nil {

View File

@@ -11,7 +11,7 @@ import (
"github.com/netbirdio/management-integrations/integrations" "github.com/netbirdio/management-integrations/integrations"
accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager" accesslogsmanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/accesslogs/manager"
"github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain" "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/domain/manager"
reverseproxymanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager" reverseproxymanager "github.com/netbirdio/netbird/management/internals/modules/reverseproxy/manager"
nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc" nbgrpc "github.com/netbirdio/netbird/management/internals/shared/grpc"
@@ -93,7 +93,7 @@ func BuildApiBlackBoxWithDBState(t testing_tools.TB, sqlFile string, expectedPee
accessLogsManager := accesslogsmanager.NewManager(store, permissionsManager, nil) accessLogsManager := accesslogsmanager.NewManager(store, permissionsManager, nil)
proxyTokenStore := nbgrpc.NewOneTimeTokenStore(1 * time.Minute) proxyTokenStore := nbgrpc.NewOneTimeTokenStore(1 * time.Minute)
proxyServiceServer := nbgrpc.NewProxyServiceServer(accessLogsManager, proxyTokenStore, nbgrpc.ProxyOIDCConfig{}, peersManager, userManager) proxyServiceServer := nbgrpc.NewProxyServiceServer(accessLogsManager, proxyTokenStore, nbgrpc.ProxyOIDCConfig{}, peersManager, userManager)
domainManager := domain.NewManager(store, proxyServiceServer) domainManager := manager.NewManager(store, proxyServiceServer)
reverseProxyManager := reverseproxymanager.NewManager(store, am, permissionsManager, proxyServiceServer, domainManager) reverseProxyManager := reverseproxymanager.NewManager(store, am, permissionsManager, proxyServiceServer, domainManager)
proxyServiceServer.SetProxyManager(reverseProxyManager) proxyServiceServer.SetProxyManager(reverseProxyManager)
am.SetServiceManager(reverseProxyManager) am.SetServiceManager(reverseProxyManager)