mirror of
https://github.com/netbirdio/netbird.git
synced 2026-07-18 20:49:56 +00:00
178 lines
6.0 KiB
Go
178 lines
6.0 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"path"
|
|
"path/filepath"
|
|
|
|
"github.com/dexidp/dex/storage"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/netbirdio/netbird/formatter/hook"
|
|
admincmd "github.com/netbirdio/netbird/management/cmd/admin"
|
|
tokencmd "github.com/netbirdio/netbird/management/cmd/token"
|
|
nbconfig "github.com/netbirdio/netbird/management/internals/server/config"
|
|
"github.com/netbirdio/netbird/management/server/activity"
|
|
activitystore "github.com/netbirdio/netbird/management/server/activity/store"
|
|
"github.com/netbirdio/netbird/management/server/store"
|
|
"github.com/netbirdio/netbird/util"
|
|
)
|
|
|
|
var adminDatadir string
|
|
|
|
// newAdminCommands creates the admin command tree with management-specific resource openers.
|
|
func newAdminCommands() *cobra.Command {
|
|
cmd := admincmd.NewCommands(admincmd.Openers{
|
|
Resources: withAdminResources,
|
|
Store: withAdminStoreOnly,
|
|
IDP: withAdminIDPOnly,
|
|
})
|
|
cmd.PersistentFlags().StringVar(&adminDatadir, "datadir", "", "Override the data directory from config (used for store.db and the default idp.db)")
|
|
return cmd
|
|
}
|
|
|
|
func newLegacyTokenCommand() *cobra.Command {
|
|
cmd := tokencmd.NewCommands(tokencmd.StoreOpener(withAdminStoreOnly))
|
|
cmd.Deprecated = "use 'admin token' instead"
|
|
cmd.PersistentFlags().StringVar(&nbconfig.MgmtConfigPath, "config", defaultMgmtConfig, "Netbird config file location")
|
|
return cmd
|
|
}
|
|
|
|
// withAdminResources initializes logging, loads config, opens the management store
|
|
// and embedded IdP storage, and calls fn.
|
|
func withAdminResources(cmd *cobra.Command, fn func(ctx context.Context, resources admincmd.Resources) error) error {
|
|
return withAdminConfig(cmd, true, func(ctx context.Context, config *nbconfig.Config, datadir string) error {
|
|
managementStore, err := openAdminStore(ctx, config, datadir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer admincmd.CloseStore(ctx, managementStore)
|
|
|
|
idpStorage, idpStorageFile, err := admincmd.OpenIDPStorage(config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer admincmd.CloseIDPStorage(idpStorage)
|
|
|
|
eventStore, esErr := openAdminEventStore(ctx, config, datadir)
|
|
if esErr != nil {
|
|
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "Warning: audit events will not be recorded: %v\n", esErr)
|
|
}
|
|
if eventStore != nil {
|
|
defer func() {
|
|
if err := eventStore.Close(ctx); err != nil {
|
|
log.Debugf("close activity event store: %v", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
return fn(ctx, admincmd.Resources{Store: managementStore, IDPStorage: idpStorage, IDPStorageFile: idpStorageFile, EventStore: eventStore})
|
|
})
|
|
}
|
|
|
|
// withAdminStoreOnly opens only the management store for admin subcommands that do not
|
|
// need embedded IdP storage.
|
|
func withAdminStoreOnly(cmd *cobra.Command, fn func(ctx context.Context, s store.Store) error) error {
|
|
return withAdminConfig(cmd, false, func(ctx context.Context, config *nbconfig.Config, datadir string) error {
|
|
managementStore, err := openAdminStore(ctx, config, datadir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer admincmd.CloseStore(ctx, managementStore)
|
|
|
|
return fn(ctx, managementStore)
|
|
})
|
|
}
|
|
|
|
func withAdminIDPOnly(cmd *cobra.Command, fn func(ctx context.Context, idpStorage storage.Storage, storageFile string) error) error {
|
|
return withAdminConfig(cmd, true, func(ctx context.Context, config *nbconfig.Config, _ string) error {
|
|
idpStorage, idpStorageFile, err := admincmd.OpenIDPStorage(config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer admincmd.CloseIDPStorage(idpStorage)
|
|
|
|
return fn(ctx, idpStorage, idpStorageFile)
|
|
})
|
|
}
|
|
|
|
func withAdminConfig(cmd *cobra.Command, applyIDPDefaults bool, fn func(ctx context.Context, config *nbconfig.Config, datadir string) error) error {
|
|
if err := util.InitLog("error", "console"); err != nil {
|
|
return fmt.Errorf("init log: %w", err)
|
|
}
|
|
|
|
ctx := context.WithValue(cmd.Context(), hook.ExecutionContextKey, hook.SystemSource) //nolint:staticcheck
|
|
|
|
config, datadir, err := loadAdminMgmtConfig(ctx, applyIDPDefaults)
|
|
if err != nil {
|
|
return fmt.Errorf("load config: %w", err)
|
|
}
|
|
|
|
return fn(ctx, config, datadir)
|
|
}
|
|
|
|
func loadAdminMgmtConfig(ctx context.Context, applyIDPDefaults bool) (*nbconfig.Config, string, error) {
|
|
config := &nbconfig.Config{}
|
|
if _, err := util.ReadJsonWithEnvSub(nbconfig.MgmtConfigPath, config); err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
if applyIDPDefaults {
|
|
if err := ApplyEmbeddedIdPConfig(ctx, config); err != nil {
|
|
return nil, "", err
|
|
}
|
|
}
|
|
|
|
datadir := config.Datadir
|
|
applyAdminDatadirOverride(config, &datadir)
|
|
return config, datadir, nil
|
|
}
|
|
|
|
func applyAdminDatadirOverride(config *nbconfig.Config, datadir *string) {
|
|
if adminDatadir == "" {
|
|
return
|
|
}
|
|
|
|
oldDatadir := *datadir
|
|
*datadir = adminDatadir
|
|
if config.EmbeddedIdP != nil && config.EmbeddedIdP.Storage.Type == "sqlite3" && isDefaultIDPStorageFile(config.EmbeddedIdP.Storage.Config.File, oldDatadir) {
|
|
config.EmbeddedIdP.Storage.Config.File = filepath.Join(*datadir, "idp.db")
|
|
}
|
|
}
|
|
|
|
func isDefaultIDPStorageFile(file, datadir string) bool {
|
|
if file == "" {
|
|
return true
|
|
}
|
|
defaultFile := filepath.Join(datadir, "idp.db")
|
|
legacyDefaultFile := path.Join(datadir, "idp.db")
|
|
legacySlashDefaultFile := path.Join(filepath.ToSlash(datadir), "idp.db")
|
|
return filepath.Clean(file) == filepath.Clean(defaultFile) ||
|
|
file == legacyDefaultFile ||
|
|
filepath.ToSlash(file) == legacySlashDefaultFile
|
|
}
|
|
|
|
func openAdminStore(ctx context.Context, config *nbconfig.Config, datadir string) (store.Store, error) {
|
|
managementStore, err := store.NewStore(ctx, config.StoreConfig.Engine, datadir, nil, true)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create store: %w", err)
|
|
}
|
|
return managementStore, nil
|
|
}
|
|
|
|
func openAdminEventStore(ctx context.Context, config *nbconfig.Config, datadir string) (activity.Store, error) {
|
|
if config.DataStoreEncryptionKey == "" {
|
|
return nil, fmt.Errorf("data store encryption key is not configured")
|
|
}
|
|
eventStore, err := activitystore.NewSqlStore(ctx, datadir, config.DataStoreEncryptionKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("open activity event store: %w", err)
|
|
}
|
|
if eventStore == nil {
|
|
return nil, fmt.Errorf("open activity event store: returned nil store")
|
|
}
|
|
return eventStore, nil
|
|
}
|