mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-24 17:13:30 +01:00
Management single account mode (#511)
This commit is contained in:
parent
04e4407ea7
commit
7218a3d563
@ -68,7 +68,7 @@ func startManagement(t *testing.T, config *mgmt.Config) (*grpc.Server, net.Liste
|
|||||||
}
|
}
|
||||||
|
|
||||||
peersUpdateManager := mgmt.NewPeersUpdateManager()
|
peersUpdateManager := mgmt.NewPeersUpdateManager()
|
||||||
accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil)
|
accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -761,7 +761,7 @@ func startManagement(port int, dataDir string) (*grpc.Server, error) {
|
|||||||
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
||||||
}
|
}
|
||||||
peersUpdateManager := server.NewPeersUpdateManager()
|
peersUpdateManager := server.NewPeersUpdateManager()
|
||||||
accountManager, err := server.BuildManager(store, peersUpdateManager, nil)
|
accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ NETBIRD_MGMT_API_ENDPOINT=https://$NETBIRD_DOMAIN:$NETBIRD_MGMT_API_PORT
|
|||||||
NETBIRD_MGMT_API_CERT_FILE="/etc/letsencrypt/live/$NETBIRD_DOMAIN/fullchain.pem"
|
NETBIRD_MGMT_API_CERT_FILE="/etc/letsencrypt/live/$NETBIRD_DOMAIN/fullchain.pem"
|
||||||
# Management Certficate key file path.
|
# Management Certficate key file path.
|
||||||
NETBIRD_MGMT_API_CERT_KEY_FILE="/etc/letsencrypt/live/$NETBIRD_DOMAIN/privkey.pem"
|
NETBIRD_MGMT_API_CERT_KEY_FILE="/etc/letsencrypt/live/$NETBIRD_DOMAIN/privkey.pem"
|
||||||
|
# By default Management single account mode is enabled and domain set to $NETBIRD_DOMAIN, you may want to set this to your user's email domain
|
||||||
|
NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN=$NETBIRD_DOMAIN
|
||||||
|
|
||||||
# Turn credentials
|
# Turn credentials
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ services:
|
|||||||
# # port and command for Let's Encrypt validation without dashboard container
|
# # port and command for Let's Encrypt validation without dashboard container
|
||||||
# - 443:443
|
# - 443:443
|
||||||
# command: ["--letsencrypt-domain", "$NETBIRD_DOMAIN", "--log-file", "console"]
|
# command: ["--letsencrypt-domain", "$NETBIRD_DOMAIN", "--log-file", "console"]
|
||||||
command: ["--port", "443", "--log-file", "console", "--disable-anonymous-metrics=$NETBIRD_DISABLE_ANONYMOUS_METRICS"]
|
command: ["--port", "443", "--log-file", "console", "--disable-anonymous-metrics=$NETBIRD_DISABLE_ANONYMOUS_METRICS", "--single-account-mode-domain=$NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN"]
|
||||||
# Coturn
|
# Coturn
|
||||||
coturn:
|
coturn:
|
||||||
image: coturn/coturn
|
image: coturn/coturn
|
||||||
|
@ -55,7 +55,7 @@ func startManagement(t *testing.T) (*grpc.Server, net.Listener) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
peersUpdateManager := mgmt.NewPeersUpdateManager()
|
peersUpdateManager := mgmt.NewPeersUpdateManager()
|
||||||
accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil)
|
accountManager, err := mgmt.BuildManager(store, peersUpdateManager, nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,12 @@ import (
|
|||||||
const ManagementLegacyPort = 33073
|
const ManagementLegacyPort = 33073
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mgmtPort int
|
mgmtPort int
|
||||||
mgmtLetsencryptDomain string
|
mgmtLetsencryptDomain string
|
||||||
certFile string
|
mgmtSingleAccModeDomain string
|
||||||
certKey string
|
certFile string
|
||||||
config *server.Config
|
certKey string
|
||||||
|
config *server.Config
|
||||||
|
|
||||||
kaep = keepalive.EnforcementPolicy{
|
kaep = keepalive.EnforcementPolicy{
|
||||||
MinTime: 15 * time.Second,
|
MinTime: 15 * time.Second,
|
||||||
@ -121,7 +122,10 @@ var (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
accountManager, err := server.BuildManager(store, peersUpdateManager, idpManager)
|
if disableSingleAccMode {
|
||||||
|
mgmtSingleAccModeDomain = ""
|
||||||
|
}
|
||||||
|
accountManager, err := server.BuildManager(store, peersUpdateManager, idpManager, mgmtSingleAccModeDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to build default manager: %v", err)
|
return fmt.Errorf("failed to build default manager: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -13,21 +13,23 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultMgmtConfigDir string
|
defaultMgmtConfigDir string
|
||||||
defaultMgmtDataDir string
|
defaultMgmtDataDir string
|
||||||
defaultMgmtConfig string
|
defaultMgmtConfig string
|
||||||
defaultLogDir string
|
defaultSingleAccModeDomain string
|
||||||
defaultLogFile string
|
defaultLogDir string
|
||||||
oldDefaultMgmtConfigDir string
|
defaultLogFile string
|
||||||
oldDefaultMgmtDataDir string
|
oldDefaultMgmtConfigDir string
|
||||||
oldDefaultMgmtConfig string
|
oldDefaultMgmtDataDir string
|
||||||
oldDefaultLogDir string
|
oldDefaultMgmtConfig string
|
||||||
oldDefaultLogFile string
|
oldDefaultLogDir string
|
||||||
mgmtDataDir string
|
oldDefaultLogFile string
|
||||||
mgmtConfig string
|
mgmtDataDir string
|
||||||
logLevel string
|
mgmtConfig string
|
||||||
logFile string
|
logLevel string
|
||||||
disableMetrics bool
|
logFile string
|
||||||
|
disableMetrics bool
|
||||||
|
disableSingleAccMode bool
|
||||||
|
|
||||||
rootCmd = &cobra.Command{
|
rootCmd = &cobra.Command{
|
||||||
Use: "netbird-mgmt",
|
Use: "netbird-mgmt",
|
||||||
@ -48,6 +50,7 @@ func init() {
|
|||||||
stopCh = make(chan int)
|
stopCh = make(chan int)
|
||||||
|
|
||||||
defaultMgmtDataDir = "/var/lib/netbird/"
|
defaultMgmtDataDir = "/var/lib/netbird/"
|
||||||
|
defaultSingleAccModeDomain = "netbird.selfhosted"
|
||||||
defaultMgmtConfigDir = "/etc/netbird"
|
defaultMgmtConfigDir = "/etc/netbird"
|
||||||
defaultLogDir = "/var/log/netbird"
|
defaultLogDir = "/var/log/netbird"
|
||||||
|
|
||||||
@ -65,6 +68,8 @@ func init() {
|
|||||||
mgmtCmd.Flags().StringVar(&mgmtDataDir, "datadir", defaultMgmtDataDir, "server data directory location")
|
mgmtCmd.Flags().StringVar(&mgmtDataDir, "datadir", defaultMgmtDataDir, "server data directory location")
|
||||||
mgmtCmd.Flags().StringVar(&mgmtConfig, "config", defaultMgmtConfig, "Netbird config file location. Config params specified via command line (e.g. datadir) have a precedence over configuration from this file")
|
mgmtCmd.Flags().StringVar(&mgmtConfig, "config", defaultMgmtConfig, "Netbird config file location. Config params specified via command line (e.g. datadir) have a precedence over configuration from this file")
|
||||||
mgmtCmd.Flags().StringVar(&mgmtLetsencryptDomain, "letsencrypt-domain", "", "a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS")
|
mgmtCmd.Flags().StringVar(&mgmtLetsencryptDomain, "letsencrypt-domain", "", "a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS")
|
||||||
|
mgmtCmd.Flags().StringVar(&mgmtSingleAccModeDomain, "single-account-mode-domain", defaultSingleAccModeDomain, "Enables single account mode. This means that all the users will be under the same account grouped by the specified domain. If the installation has more than one account, the property is ineffective. Enabled by default with the default domain "+defaultSingleAccModeDomain)
|
||||||
|
mgmtCmd.Flags().BoolVar(&disableSingleAccMode, "disable-single-account-mode", false, "If set to true, disables single account mode. The --single-account-mode-domain property will be ignored and every new user will have a separate NetBird account.")
|
||||||
mgmtCmd.Flags().StringVar(&certFile, "cert-file", "", "Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
|
mgmtCmd.Flags().StringVar(&certFile, "cert-file", "", "Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
|
||||||
mgmtCmd.Flags().StringVar(&certKey, "cert-key", "", "Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
|
mgmtCmd.Flags().StringVar(&certKey, "cert-key", "", "Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect")
|
||||||
mgmtCmd.Flags().BoolVar(&disableMetrics, "disable-anonymous-metrics", false, "disables push of anonymous usage metrics to NetBird")
|
mgmtCmd.Flags().BoolVar(&disableMetrics, "disable-anonymous-metrics", false, "disables push of anonymous usage metrics to NetBird")
|
||||||
|
@ -106,6 +106,13 @@ type DefaultAccountManager struct {
|
|||||||
idpManager idp.Manager
|
idpManager idp.Manager
|
||||||
cacheManager cache.CacheInterface[[]*idp.UserData]
|
cacheManager cache.CacheInterface[[]*idp.UserData]
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
|
|
||||||
|
// singleAccountMode indicates whether the instance has a single account.
|
||||||
|
// If true, then every new user will end up under the same account.
|
||||||
|
// This value will be set to false if management service has more than one account.
|
||||||
|
singleAccountMode bool
|
||||||
|
// singleAccountModeDomain is a domain to use in singleAccountMode setup
|
||||||
|
singleAccountModeDomain string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account represents a unique account of the system
|
// Account represents a unique account of the system
|
||||||
@ -195,9 +202,8 @@ func (a *Account) GetGroupAll() (*Group, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BuildManager creates a new DefaultAccountManager with a provided Store
|
// BuildManager creates a new DefaultAccountManager with a provided Store
|
||||||
func BuildManager(
|
func BuildManager(store Store, peersUpdateManager *PeersUpdateManager, idpManager idp.Manager,
|
||||||
store Store, peersUpdateManager *PeersUpdateManager, idpManager idp.Manager,
|
singleAccountModeDomain string) (*DefaultAccountManager, error) {
|
||||||
) (*DefaultAccountManager, error) {
|
|
||||||
am := &DefaultAccountManager{
|
am := &DefaultAccountManager{
|
||||||
Store: store,
|
Store: store,
|
||||||
mux: sync.Mutex{},
|
mux: sync.Mutex{},
|
||||||
@ -207,11 +213,20 @@ func BuildManager(
|
|||||||
cacheMux: sync.Mutex{},
|
cacheMux: sync.Mutex{},
|
||||||
cacheLoading: map[string]chan struct{}{},
|
cacheLoading: map[string]chan struct{}{},
|
||||||
}
|
}
|
||||||
|
allAccounts := store.GetAllAccounts()
|
||||||
|
// enable single account mode only if configured by user and number of existing accounts is not grater than 1
|
||||||
|
am.singleAccountMode = singleAccountModeDomain != "" && len(allAccounts) <= 1
|
||||||
|
if am.singleAccountMode {
|
||||||
|
am.singleAccountModeDomain = singleAccountModeDomain
|
||||||
|
log.Infof("single account mode enabled, accounts number %d", len(allAccounts))
|
||||||
|
} else {
|
||||||
|
log.Infof("single account mode disabled, accounts number %d", len(allAccounts))
|
||||||
|
}
|
||||||
|
|
||||||
// if account has not default group
|
// if account doesn't have a default group
|
||||||
// we create 'all' group and add all peers into it
|
// we create 'all' group and add all peers into it
|
||||||
// also we create default rule with source as destination
|
// also we create default rule with source as destination
|
||||||
for _, account := range store.GetAllAccounts() {
|
for _, account := range allAccounts {
|
||||||
_, err := account.GetGroupAll()
|
_, err := account.GetGroupAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
addAllGroup(account)
|
addAllGroup(account)
|
||||||
@ -221,10 +236,10 @@ func BuildManager(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gocacheClient := gocache.New(CacheExpirationMax, 30*time.Minute)
|
goCacheClient := gocache.New(CacheExpirationMax, 30*time.Minute)
|
||||||
gocacheStore := cacheStore.NewGoCache(gocacheClient)
|
goCacheStore := cacheStore.NewGoCache(goCacheClient)
|
||||||
|
|
||||||
am.cacheManager = cache.NewLoadable[[]*idp.UserData](am.loadAccount, cache.New[[]*idp.UserData](gocacheStore))
|
am.cacheManager = cache.NewLoadable[[]*idp.UserData](am.loadAccount, cache.New[[]*idp.UserData](goCacheStore))
|
||||||
|
|
||||||
if !isNil(am.idpManager) {
|
if !isNil(am.idpManager) {
|
||||||
go func() {
|
go func() {
|
||||||
@ -604,6 +619,15 @@ func (am *DefaultAccountManager) redeemInvite(account *Account, userID string) e
|
|||||||
|
|
||||||
// GetAccountFromToken returns an account associated with this token
|
// GetAccountFromToken returns an account associated with this token
|
||||||
func (am *DefaultAccountManager) GetAccountFromToken(claims jwtclaims.AuthorizationClaims) (*Account, error) {
|
func (am *DefaultAccountManager) GetAccountFromToken(claims jwtclaims.AuthorizationClaims) (*Account, error) {
|
||||||
|
|
||||||
|
if am.singleAccountMode && am.singleAccountModeDomain != "" {
|
||||||
|
// This section is mostly related to self-hosted installations.
|
||||||
|
// We override incoming domain claims to group users under a single account.
|
||||||
|
claims.Domain = am.singleAccountModeDomain
|
||||||
|
claims.DomainCategory = PrivateCategory
|
||||||
|
log.Infof("overriding JWT Domain and DomainCategory claims since single account mode is enabled")
|
||||||
|
}
|
||||||
|
|
||||||
account, err := am.getAccountWithAuthorizationClaims(claims)
|
account, err := am.getAccountWithAuthorizationClaims(claims)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -962,7 +962,7 @@ func createManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return BuildManager(store, NewPeersUpdateManager(), nil)
|
return BuildManager(store, NewPeersUpdateManager(), nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createStore(t *testing.T) (Store, error) {
|
func createStore(t *testing.T) (Store, error) {
|
||||||
|
@ -403,7 +403,7 @@ func startManagement(t *testing.T, port int, config *Config) (*grpc.Server, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
peersUpdateManager := NewPeersUpdateManager()
|
peersUpdateManager := NewPeersUpdateManager()
|
||||||
accountManager, err := BuildManager(store, peersUpdateManager, nil)
|
accountManager, err := BuildManager(store, peersUpdateManager, nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -493,7 +493,7 @@ func startServer(config *server.Config) (*grpc.Server, net.Listener) {
|
|||||||
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
log.Fatalf("failed creating a store: %s: %v", config.Datadir, err)
|
||||||
}
|
}
|
||||||
peersUpdateManager := server.NewPeersUpdateManager()
|
peersUpdateManager := server.NewPeersUpdateManager()
|
||||||
accountManager, err := server.BuildManager(store, peersUpdateManager, nil)
|
accountManager, err := server.BuildManager(store, peersUpdateManager, nil, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed creating a manager: %v", err)
|
log.Fatalf("failed creating a manager: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -865,7 +865,7 @@ func createNSManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return BuildManager(store, NewPeersUpdateManager(), nil)
|
return BuildManager(store, NewPeersUpdateManager(), nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNSStore(t *testing.T) (Store, error) {
|
func createNSStore(t *testing.T) (Store, error) {
|
||||||
|
@ -778,7 +778,7 @@ func createRouterManager(t *testing.T) (*DefaultAccountManager, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return BuildManager(store, NewPeersUpdateManager(), nil)
|
return BuildManager(store, NewPeersUpdateManager(), nil, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createRouterStore(t *testing.T) (Store, error) {
|
func createRouterStore(t *testing.T) (Store, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user