From ba2553b98c5b1e3d798ecde23ef67040eae334d9 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 2 Oct 2024 04:55:57 -0400 Subject: [PATCH 1/3] Added support for daemon JWT authorization --- go.mod | 9 +-- go.sum | 16 ++--- hyperdrive-cli/client/auth.go | 69 +++++++++++++++++++ hyperdrive-cli/client/client.go | 30 ++++++-- hyperdrive-cli/client/compose.go | 2 +- hyperdrive-cli/client/config.go | 10 +-- hyperdrive-cli/client/templating.go | 12 ++++ .../commands/constellation/node/commands.go | 1 + .../constellation/node/register-node.go | 23 +++++-- hyperdrive-cli/commands/service/config.go | 4 +- hyperdrive-cli/commands/service/start.go | 6 ++ hyperdrive-cli/commands/service/terminate.go | 2 +- hyperdrive-cli/hyperdrive.go | 10 +-- hyperdrive-cli/utils/context/context.go | 8 +-- install/deploy/templates/daemon.tmpl | 2 + .../modules/constellation/cs_daemon.tmpl | 4 ++ .../modules/stakewise/sw_daemon.tmpl | 4 ++ internal/tests/cfg_test.go | 13 +++- 18 files changed, 179 insertions(+), 46 deletions(-) create mode 100644 hyperdrive-cli/client/auth.go diff --git a/go.mod b/go.mod index 2563245..9ca82de 100644 --- a/go.mod +++ b/go.mod @@ -15,13 +15,13 @@ require ( github.com/goccy/go-json v0.10.3 github.com/mholt/archiver/v4 v4.0.0-alpha.8 github.com/mitchellh/go-homedir v1.1.0 - github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241001194414-bd5ba3c5fde2 - github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241001192501-b11ba9e5209f - github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241001200731-88e20a15b576 + github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d + github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4 + github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f github.com/nodeset-org/osha v0.3.1-0.20240927160812-d66358d4e091 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/rivo/tview v0.0.0-20230208211350-7dfff1ce7854 // DO NOT UPGRADE - github.com/rocket-pool/node-manager-core v0.5.2-0.20241001041416-40f4fb819f98 + github.com/rocket-pool/node-manager-core v0.5.2-0.20241002072934-89c9cc081cf6 github.com/rocket-pool/rocketpool-go/v2 v2.0.0-b2.0.20240709170030-c27aeb5fb99b github.com/stretchr/testify v1.9.0 github.com/tyler-smith/go-bip39 v1.1.0 @@ -85,6 +85,7 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect diff --git a/go.sum b/go.sum index be1287f..fc1142d 100644 --- a/go.sum +++ b/go.sum @@ -444,12 +444,12 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241001194414-bd5ba3c5fde2 h1:PM6k+J0uXHtWR2W55c6GrSfqNVHi02/+HDx3wQ57YEk= -github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241001194414-bd5ba3c5fde2/go.mod h1:hUQX0mH9zxopcQKLE2xenk6TpG+X1ZiqAZ19x6meY/U= -github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241001192501-b11ba9e5209f h1:iAxCtnQkT8UGunXIyGNdhsVcqwQve0SefNMdoja3kCc= -github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241001192501-b11ba9e5209f/go.mod h1:KCZ/EptpaWrk/O2jYAUH2hDYt6Mrcjf68fVOeT8fuew= -github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241001200731-88e20a15b576 h1:ZRw5ssx0ZruQJvu4UvsT+UGfTuMnSRCZy1VE2UPjeWo= -github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241001200731-88e20a15b576/go.mod h1:6UypLzyI/G86ZS1jpT6J0hovHoAihqnMHEUYaXAPv5U= +github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d h1:dCoRAdCOw7Ow/mnPupF+/klClG097TFfF9913AQG+dw= +github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d/go.mod h1:0LcBrdrHkkAs3m7bFRIg9Fb5HbBJazJE3lvgy+QbST8= +github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4 h1:sBdg5zBUwDtjNYfmx8PxvvFWiSKsQSiBKN9ZsJZWib0= +github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4/go.mod h1:VXYiN0ZrXbeNALJLa0sin4AzlSrFuGH8gW1YSywoVoI= +github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f h1:OCJ9aniDFD5vR1Y6kcZZo4HzORNbISfjPF5QslyRY3Y= +github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f/go.mod h1:hGpWV7iJwpJg/8pbQnv3t6oGWoMZBHyeY24btNDP324= github.com/nodeset-org/nodeset-client-go v1.0.1-0.20240927160821-e348e05e2363 h1:iivCknAFZlpxPwbIDjPc9E2bnj55c2STrXT9MvuMzQM= github.com/nodeset-org/nodeset-client-go v1.0.1-0.20240927160821-e348e05e2363/go.mod h1:slpwejkJ/vYU9SKA3SYw4hIPJLzDUeQxcx+Cm04kkIA= github.com/nodeset-org/osha v0.3.1-0.20240927160812-d66358d4e091 h1:oAs4/Yx4jnsNdWh3vTKum1sXC8VCvsY1H2VFSRRkgjc= @@ -525,8 +525,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rocket-pool/batch-query v1.0.0 h1:5HejmT1n1fIdLIqUhTNwbkG2PGOPl3IVjCpFQcQZ4I4= github.com/rocket-pool/batch-query v1.0.0/go.mod h1:d1CmxShzk0fioJ4yX0eFGhz2an1odnW/LZ2cp3eDGIQ= -github.com/rocket-pool/node-manager-core v0.5.2-0.20241001041416-40f4fb819f98 h1:/vmzEAVs15gRK7q8lUYi1+MJd0XhxJwPe3zMdRB+3c8= -github.com/rocket-pool/node-manager-core v0.5.2-0.20241001041416-40f4fb819f98/go.mod h1:/H1wq3skacZi4zjgnKTtnm0wBLJH7H5r0CvLtWFs19Y= +github.com/rocket-pool/node-manager-core v0.5.2-0.20241002072934-89c9cc081cf6 h1:rn0t1IoOEy7ecETHRIGBQd40GDuqT4lK8MeWsfoGKPU= +github.com/rocket-pool/node-manager-core v0.5.2-0.20241002072934-89c9cc081cf6/go.mod h1:/H1wq3skacZi4zjgnKTtnm0wBLJH7H5r0CvLtWFs19Y= github.com/rocket-pool/rocketpool-go/v2 v2.0.0-b2.0.20240709170030-c27aeb5fb99b h1:39UmJzNR71/OMIzblEY9wq+3nojGa/gQOJJpLBa6XcE= github.com/rocket-pool/rocketpool-go/v2 v2.0.0-b2.0.20240709170030-c27aeb5fb99b/go.mod h1:pcY43H/m5pjr7zacrsKVaXnXfKKi1UV08VDPUwxbJkc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= diff --git a/hyperdrive-cli/client/auth.go b/hyperdrive-cli/client/auth.go new file mode 100644 index 0000000..9e257d6 --- /dev/null +++ b/hyperdrive-cli/client/auth.go @@ -0,0 +1,69 @@ +package client + +import ( + "fmt" + "os" + "path/filepath" + + csconfig "github.com/nodeset-org/hyperdrive-constellation/shared/config" + "github.com/nodeset-org/hyperdrive-daemon/shared/auth" + hdconfig "github.com/nodeset-org/hyperdrive-daemon/shared/config" + swconfig "github.com/nodeset-org/hyperdrive-stakewise/shared/config" +) + +const ( + authDirMode os.FileMode = 0700 +) + +var ( + hdApiKeyRelPath string = filepath.Join(hdconfig.SecretsDir, hdconfig.DaemonKeyFilename) + swApiKeyRelPath string = filepath.Join(hdconfig.SecretsDir, hdconfig.ModulesName, swconfig.ModuleName, hdconfig.DaemonKeyFilename) + csApiKeyRelPath string = filepath.Join(hdconfig.SecretsDir, hdconfig.ModulesName, csconfig.ModuleName, hdconfig.DaemonKeyFilename) +) + +// Create the metrics and modules folders, and deploy the config templates for Prometheus and Grafana +func (c *HyperdriveClient) GenerateDaemonAuthKeys(config *GlobalConfig) error { + // Make sure the secrets path exists + secretsDirPath := filepath.Join(c.Context.UserDirPath, hdconfig.SecretsDir) + modulesDirPath := filepath.Join(secretsDirPath, hdconfig.ModulesName) + err := os.MkdirAll(modulesDirPath, authDirMode) + if err != nil { + return fmt.Errorf("error creating secrets and modules directories [%s]: %w", modulesDirPath, err) + } + + // Create the API key for the Hyperdrive daemon + hdApiKeyPath := filepath.Join(c.Context.UserDirPath, hdApiKeyRelPath) + err = auth.GenerateAuthKeyIfNotPresent(hdApiKeyPath, auth.DefaultKeyLength) + if err != nil { + return fmt.Errorf("error generating Hyperdrive daemon API key: %w", err) + } + + // Create the API key for the StakeWise module if enabled + if config.StakeWise.Enabled.Value { + swDirPath := filepath.Join(modulesDirPath, swconfig.ModuleName) + err := os.MkdirAll(swDirPath, authDirMode) + if err != nil { + return fmt.Errorf("error creating StakeWise API key module directory [%s]: %w", swDirPath, err) + } + swApiKeyPath := filepath.Join(c.Context.UserDirPath, swApiKeyRelPath) + err = auth.GenerateAuthKeyIfNotPresent(swApiKeyPath, auth.DefaultKeyLength) + if err != nil { + return fmt.Errorf("error generating StakeWise module API key: %w", err) + } + } + + // Create the API key for the Constellation module if enabled + if config.Constellation.Enabled.Value { + csDirPath := filepath.Join(modulesDirPath, csconfig.ModuleName) + err := os.MkdirAll(csDirPath, authDirMode) + if err != nil { + return fmt.Errorf("error creating Constellation API key module directory [%s]: %w", csDirPath, err) + } + csApiKeyPath := filepath.Join(c.Context.UserDirPath, csApiKeyRelPath) + err = auth.GenerateAuthKeyIfNotPresent(csApiKeyPath, auth.DefaultKeyLength) + if err != nil { + return fmt.Errorf("error generating Constellation module API key: %w", err) + } + } + return nil +} diff --git a/hyperdrive-cli/client/client.go b/hyperdrive-cli/client/client.go index 9ec6581..b152e3c 100644 --- a/hyperdrive-cli/client/client.go +++ b/hyperdrive-cli/client/client.go @@ -4,13 +4,15 @@ import ( "fmt" "log/slog" "net/http/httptrace" + "path/filepath" docker "github.com/docker/docker/client" "github.com/fatih/color" csclient "github.com/nodeset-org/hyperdrive-constellation/client" csconfig "github.com/nodeset-org/hyperdrive-constellation/shared/config" "github.com/nodeset-org/hyperdrive-daemon/client" - "github.com/nodeset-org/hyperdrive-daemon/shared/config" + "github.com/nodeset-org/hyperdrive-daemon/shared/auth" + hdconfig "github.com/nodeset-org/hyperdrive-daemon/shared/config" swclient "github.com/nodeset-org/hyperdrive-stakewise/client" swconfig "github.com/nodeset-org/hyperdrive-stakewise/shared/config" "github.com/nodeset-org/hyperdrive/hyperdrive-cli/utils/context" @@ -61,7 +63,7 @@ func NewHyperdriveClientFromCtx(c *cli.Context) (*HyperdriveClient, error) { // Create new Hyperdrive client from a custom context func NewHyperdriveClientFromHyperdriveCtx(hdCtx *context.HyperdriveContext) (*HyperdriveClient, error) { - logger := log.NewTerminalLogger(hdCtx.DebugEnabled, terminalLogColor).With(slog.String(log.OriginKey, config.HyperdriveDaemonRoute)) + logger := log.NewTerminalLogger(hdCtx.DebugEnabled, terminalLogColor).With(slog.String(log.OriginKey, hdconfig.HyperdriveDaemonRoute)) // Create the tracer if required var tracer *httptrace.ClientTrace @@ -94,12 +96,18 @@ func NewHyperdriveClientFromHyperdriveCtx(hdCtx *context.HyperdriveContext) (*Hy return nil, fmt.Errorf("error loading config: %w", err) } - url, err = url.Parse(fmt.Sprintf("http://localhost:%d/%s", cfg.Hyperdrive.ApiPort.Value, config.HyperdriveApiClientRoute)) + url, err = url.Parse(fmt.Sprintf("http://localhost:%d/%s", cfg.Hyperdrive.ApiPort.Value, hdconfig.HyperdriveApiClientRoute)) if err != nil { return nil, fmt.Errorf("error parsing Hyperdrive API URL: %w", err) } } - hdClient.Api = client.NewApiClient(url, logger, tracer) + + // Create the auth manager + authPath := filepath.Join(hdCtx.UserDirPath, hdApiKeyRelPath) + authMgr := auth.NewAuthorizationManager(authPath) + + // Create the API client + hdClient.Api = client.NewApiClient(url, logger, tracer, authMgr) return hdClient, nil } @@ -148,7 +156,12 @@ func NewStakewiseClientFromHyperdriveCtx(hdCtx *context.HyperdriveContext, hdCli } } - swClient.Api = swclient.NewApiClient(url, logger, tracer) + // Create the auth manager + authPath := filepath.Join(hdCtx.UserDirPath, swApiKeyRelPath) + authMgr := auth.NewAuthorizationManager(authPath) + + // Create the API client + swClient.Api = swclient.NewApiClient(url, logger, tracer, authMgr) return swClient, nil } @@ -191,7 +204,12 @@ func NewConstellationClientFromCtx(c *cli.Context, hdClient *HyperdriveClient) ( } } - csClient.Api = csclient.NewApiClient(url, logger, tracer) + // Create the auth manager + authPath := filepath.Join(hdCtx.UserDirPath, csApiKeyRelPath) + authMgr := auth.NewAuthorizationManager(authPath) + + // Create the API client + csClient.Api = csclient.NewApiClient(url, logger, tracer, authMgr) return csClient, nil } diff --git a/hyperdrive-cli/client/compose.go b/hyperdrive-cli/client/compose.go index 22d1987..2cc3db9 100644 --- a/hyperdrive-cli/client/compose.go +++ b/hyperdrive-cli/client/compose.go @@ -18,7 +18,7 @@ import ( // Build a docker compose command func (c *HyperdriveClient) compose(composeFiles []string, args string) (string, error) { // Get the expanded config path - expandedConfigPath, err := homedir.Expand(c.Context.ConfigPath) + expandedConfigPath, err := homedir.Expand(c.Context.UserDirPath) if err != nil { return "", err } diff --git a/hyperdrive-cli/client/config.go b/hyperdrive-cli/client/config.go index 9a507b1..7105933 100644 --- a/hyperdrive-cli/client/config.go +++ b/hyperdrive-cli/client/config.go @@ -28,7 +28,7 @@ func (c *HyperdriveClient) LoadConfig() (*GlobalConfig, bool, error) { return c.cfg, c.isNewCfg, nil } - settingsFilePath := filepath.Join(c.Context.ConfigPath, SettingsFile) + settingsFilePath := filepath.Join(c.Context.UserDirPath, SettingsFile) expandedPath, err := homedir.Expand(settingsFilePath) if err != nil { return nil, false, fmt.Errorf("error expanding settings file path: %w", err) @@ -46,7 +46,7 @@ func (c *HyperdriveClient) LoadConfig() (*GlobalConfig, bool, error) { } // Config wasn't loaded, but there was no error - we should create one. - hdCfg, err := hdconfig.NewHyperdriveConfig(c.Context.ConfigPath, c.Context.HyperdriveNetworkSettings) + hdCfg, err := hdconfig.NewHyperdriveConfig(c.Context.UserDirPath, c.Context.HyperdriveNetworkSettings) if err != nil { return nil, false, fmt.Errorf("error creating Hyperdrive config: %w", err) } @@ -68,7 +68,7 @@ func (c *HyperdriveClient) LoadConfig() (*GlobalConfig, bool, error) { // Load the backup config func (c *HyperdriveClient) LoadBackupConfig() (*GlobalConfig, error) { - settingsFilePath := filepath.Join(c.Context.ConfigPath, BackupSettingsFile) + settingsFilePath := filepath.Join(c.Context.UserDirPath, BackupSettingsFile) expandedPath, err := homedir.Expand(settingsFilePath) if err != nil { return nil, fmt.Errorf("error expanding backup settings file path: %w", err) @@ -79,7 +79,7 @@ func (c *HyperdriveClient) LoadBackupConfig() (*GlobalConfig, error) { // Save the config func (c *HyperdriveClient) SaveConfig(cfg *GlobalConfig) error { - settingsFileDirectoryPath, err := homedir.Expand(c.Context.ConfigPath) + settingsFileDirectoryPath, err := homedir.Expand(c.Context.UserDirPath) if err != nil { return err } @@ -97,7 +97,7 @@ func (c *HyperdriveClient) SaveConfig(cfg *GlobalConfig) error { // Create the metrics and modules folders, and deploy the config templates for Prometheus and Grafana func (c *HyperdriveClient) DeployMetricsConfigurations(config *GlobalConfig) error { // Make sure the metrics path exists - metricsDirPath := filepath.Join(c.Context.ConfigPath, metricsDir) + metricsDirPath := filepath.Join(c.Context.UserDirPath, metricsDir) modulesDirPath := filepath.Join(metricsDirPath, hdconfig.ModulesName) err := os.MkdirAll(modulesDirPath, metricsDirMode) if err != nil { diff --git a/hyperdrive-cli/client/templating.go b/hyperdrive-cli/client/templating.go index 91d4ef7..16d1b5e 100644 --- a/hyperdrive-cli/client/templating.go +++ b/hyperdrive-cli/client/templating.go @@ -20,3 +20,15 @@ func (c *GlobalConfig) ModulesDirectory() string { func (c *GlobalConfig) ValidatorsDirectory() string { return config.ValidatorsDirectory } + +func (c *GlobalConfig) HyperdriveApiKeyPath() string { + return hdApiKeyRelPath +} + +func (c *GlobalConfig) StakeWiseApiKeyPath() string { + return swApiKeyRelPath +} + +func (c *GlobalConfig) ConstellationApiKeyPath() string { + return csApiKeyRelPath +} diff --git a/hyperdrive-cli/commands/constellation/node/commands.go b/hyperdrive-cli/commands/constellation/node/commands.go index 0ac5210..9efade3 100644 --- a/hyperdrive-cli/commands/constellation/node/commands.go +++ b/hyperdrive-cli/commands/constellation/node/commands.go @@ -30,6 +30,7 @@ func RegisterCommands(cmd *cli.Command, name string, aliases []string) { Aliases: []string{"r"}, Flags: []cli.Flag{ utils.YesFlag, + registerForceFlag, }, Usage: "Registers your node with Constellation so you can create and run minipools.", Action: func(c *cli.Context) error { diff --git a/hyperdrive-cli/commands/constellation/node/register-node.go b/hyperdrive-cli/commands/constellation/node/register-node.go index f87349f..b84c9c6 100644 --- a/hyperdrive-cli/commands/constellation/node/register-node.go +++ b/hyperdrive-cli/commands/constellation/node/register-node.go @@ -11,6 +11,13 @@ import ( "github.com/urfave/cli/v2" ) +var ( + registerForceFlag *cli.BoolFlag = &cli.BoolFlag{ + Name: "force", + Usage: "Force registration on nodeset.io, even if the node is already registered with the Constellation contracts", + } +) + func registerNode(c *cli.Context) error { // Get the client hd, err := client.NewHyperdriveClientFromCtx(c) @@ -23,13 +30,15 @@ func registerNode(c *cli.Context) error { } // Check if the node's already registered - csRegResponse, err := cs.Api.Node.GetRegistrationStatus() - if err != nil { - return err - } - if csRegResponse.Data.Registered { - fmt.Println("Your node is already registered with Constellation.") - return nil + if !c.Bool(registerForceFlag.Name) { + csRegResponse, err := cs.Api.Node.GetRegistrationStatus() + if err != nil { + return err + } + if csRegResponse.Data.Registered { + fmt.Println("Your node is already registered with Constellation.") + return nil + } } // Check if the node's registered with NodeSet diff --git a/hyperdrive-cli/commands/service/config.go b/hyperdrive-cli/commands/service/config.go index 9033f2a..e6e2d36 100644 --- a/hyperdrive-cli/commands/service/config.go +++ b/hyperdrive-cli/commands/service/config.go @@ -31,9 +31,9 @@ func configureService(c *cli.Context) error { } // Make sure the config directory exists first - err = os.MkdirAll(hd.Context.ConfigPath, 0700) + err = os.MkdirAll(hd.Context.UserDirPath, 0700) if err != nil { - fmt.Printf("%sYour Hyperdrive user configuration directory of [%s] could not be created:%s.%s\n", terminal.ColorYellow, hd.Context.ConfigPath, err.Error(), terminal.ColorReset) + fmt.Printf("%sYour Hyperdrive user configuration directory of [%s] could not be created:%s.%s\n", terminal.ColorYellow, hd.Context.UserDirPath, err.Error(), terminal.ColorReset) return nil } diff --git a/hyperdrive-cli/commands/service/start.go b/hyperdrive-cli/commands/service/start.go index 0b0589c..0ea9d0e 100644 --- a/hyperdrive-cli/commands/service/start.go +++ b/hyperdrive-cli/commands/service/start.go @@ -63,6 +63,12 @@ func startService(c *cli.Context, ignoreConfigSuggestion bool) error { } } + // Generate the daemon API keys + err = hd.GenerateDaemonAuthKeys(cfg) + if err != nil { + return fmt.Errorf("error generating daemon API keys: %w", err) + } + // Validate the config errors := cfg.Validate() if len(errors) > 0 { diff --git a/hyperdrive-cli/commands/service/terminate.go b/hyperdrive-cli/commands/service/terminate.go index 8cf3594..f34df41 100644 --- a/hyperdrive-cli/commands/service/terminate.go +++ b/hyperdrive-cli/commands/service/terminate.go @@ -24,5 +24,5 @@ func terminateService(c *cli.Context) error { } // Stop service - return hd.TerminateService(getComposeFiles(c), hd.Context.ConfigPath) + return hd.TerminateService(getComposeFiles(c), hd.Context.UserDirPath) } diff --git a/hyperdrive-cli/hyperdrive.go b/hyperdrive-cli/hyperdrive.go index c516721..6bb713b 100644 --- a/hyperdrive-cli/hyperdrive.go +++ b/hyperdrive-cli/hyperdrive.go @@ -42,7 +42,7 @@ var ( Aliases: []string{"r"}, Usage: "Allow hyperdrive to be run as the root user", } - configPathFlag *cli.StringFlag = &cli.StringFlag{ + userDirPathFlag *cli.StringFlag = &cli.StringFlag{ Name: "config-path", Aliases: []string{"c"}, Usage: "Directory to install and save all of Hyperdrive's configuration and data to", @@ -114,7 +114,7 @@ func main() { // Set application flags app.Flags = []cli.Flag{ allowRootFlag, - configPathFlag, + userDirPathFlag, apiAddressFlag, maxFeeFlag, maxPriorityFeeFlag, @@ -179,14 +179,14 @@ func setDefaultPaths() { } // Default config folder path - defaultConfigPath := filepath.Join(homeDir, defaultConfigFolder) - configPathFlag.Value = defaultConfigPath + defaultUserDirPath := filepath.Join(homeDir, defaultConfigFolder) + userDirPathFlag.Value = defaultUserDirPath } // Validate the global flags func validateFlags(c *cli.Context) (*context.HyperdriveContext, error) { // Make sure the config directory exists - configPath := c.String(configPathFlag.Name) + configPath := c.String(userDirPathFlag.Name) path, err := homedir.Expand(strings.TrimSpace(configPath)) if err != nil { return nil, fmt.Errorf("error expanding config path [%s]: %w", configPath, err) diff --git a/hyperdrive-cli/utils/context/context.go b/hyperdrive-cli/utils/context/context.go index bc20632..358cc0d 100644 --- a/hyperdrive-cli/utils/context/context.go +++ b/hyperdrive-cli/utils/context/context.go @@ -21,8 +21,8 @@ const ( type HyperdriveContext struct { *InstallationInfo - // The path to the configuration file - ConfigPath string + // The path to the Hyperdrive user directory + UserDirPath string // The max fee for transactions MaxFee float64 @@ -56,12 +56,12 @@ type HyperdriveContext struct { } // Creates a new Hyperdrive context. If installationInfo is nil, a new one will be created using the system configuration. -func NewHyperdriveContext(cfgPath string, installationInfo *InstallationInfo) *HyperdriveContext { +func NewHyperdriveContext(userDirPath string, installationInfo *InstallationInfo) *HyperdriveContext { if installationInfo == nil { installationInfo = NewInstallationInfo() } return &HyperdriveContext{ - ConfigPath: cfgPath, + UserDirPath: userDirPath, InstallationInfo: installationInfo, } } diff --git a/install/deploy/templates/daemon.tmpl b/install/deploy/templates/daemon.tmpl index 0d4f431..9c582dd 100644 --- a/install/deploy/templates/daemon.tmpl +++ b/install/deploy/templates/daemon.tmpl @@ -29,6 +29,8 @@ services: - "0.0.0.0" # Open to all Docker traffic - --port - "{{.Hyperdrive.ApiPort}}" + - --api-key + - "{{.Hyperdrive.GetUserDirectory}}/{{.HyperdriveApiKeyPath}}" networks: - net {{- range $network := .Hyperdrive.GetAdditionalDockerNetworks}} diff --git a/install/deploy/templates/modules/constellation/cs_daemon.tmpl b/install/deploy/templates/modules/constellation/cs_daemon.tmpl index 8c59ee3..febbe69 100644 --- a/install/deploy/templates/modules/constellation/cs_daemon.tmpl +++ b/install/deploy/templates/modules/constellation/cs_daemon.tmpl @@ -30,6 +30,10 @@ services: - "0.0.0.0" # Open to all Docker traffic - --port - "{{.Constellation.ApiPort}}" + - --api-key + - "{{.Hyperdrive.GetUserDirectory}}//{{.ConstellationApiKeyPath}}" + - --hd-api-key + - "{{.Hyperdrive.GetUserDirectory}}//{{.HyperdriveApiKeyPath}}" networks: - net {{- range $network := .Hyperdrive.GetAdditionalDockerNetworks}} diff --git a/install/deploy/templates/modules/stakewise/sw_daemon.tmpl b/install/deploy/templates/modules/stakewise/sw_daemon.tmpl index b218580..21ca21b 100644 --- a/install/deploy/templates/modules/stakewise/sw_daemon.tmpl +++ b/install/deploy/templates/modules/stakewise/sw_daemon.tmpl @@ -30,6 +30,10 @@ services: - "0.0.0.0" # Open to all Docker traffic - --port - "{{.StakeWise.ApiPort}}" + - --api-key + - "{{.Hyperdrive.GetUserDirectory}}//{{.StakeWiseApiKeyPath}}" + - --hd-api-key + - "{{.Hyperdrive.GetUserDirectory}}//{{.HyperdriveApiKeyPath}}" networks: - net {{- range $network := .Hyperdrive.GetAdditionalDockerNetworks}} diff --git a/internal/tests/cfg_test.go b/internal/tests/cfg_test.go index b2767ec..cf25e1b 100644 --- a/internal/tests/cfg_test.go +++ b/internal/tests/cfg_test.go @@ -12,6 +12,7 @@ import ( hdcommon "github.com/nodeset-org/hyperdrive-daemon/common" modservices "github.com/nodeset-org/hyperdrive-daemon/module-utils/services" hdserver "github.com/nodeset-org/hyperdrive-daemon/server" + "github.com/nodeset-org/hyperdrive-daemon/shared/auth" hdconfig "github.com/nodeset-org/hyperdrive-daemon/shared/config" swcommon "github.com/nodeset-org/hyperdrive-stakewise/common" swconfig "github.com/nodeset-org/hyperdrive-stakewise/shared/config" @@ -22,6 +23,10 @@ import ( "github.com/stretchr/testify/require" ) +const ( + hdTestApiKey string = "hd-api-key" +) + func TestNewConfig_Holesky(t *testing.T) { // Take a snapshot, revert at the end snapshotName, err := testMgr.CreateCustomSnapshot(osha.Service_Filesystem) @@ -82,10 +87,12 @@ func TestNewConfig_Holesky(t *testing.T) { t.Log("Config saved successfully") // Make a Hyperdrive daemon server - hdSp, err := hdcommon.NewHyperdriveServiceProvider(hdCtx.ConfigPath, hdCtx.NetworksDir) + hdSp, err := hdcommon.NewHyperdriveServiceProvider(hdCtx.UserDirPath, hdCtx.NetworksDir) require.NoError(t, err) hdWg := &sync.WaitGroup{} - hdServer, err := hdserver.NewServerManager(hdSp, "localhost", 0, hdWg) + authMgr := auth.NewAuthorizationManager("") + authMgr.SetKey([]byte(hdTestApiKey)) + hdServer, err := hdserver.NewServerManager(hdSp, "localhost", 0, hdWg, authMgr) require.NoError(t, err) hdServerPort := hdServer.GetPort() defer hdServer.Stop() @@ -100,7 +107,7 @@ func TestNewConfig_Holesky(t *testing.T) { require.NoError(t, err) modSp, err := modservices.NewModuleServiceProvider(hdApiUrl, swModDir, swconfig.ModuleName, swconfig.ClientLogName, func(hdCfg *hdconfig.HyperdriveConfig) (*swconfig.StakeWiseConfig, error) { return swconfig.NewStakeWiseConfig(hdCfg, swSettings) - }) + }, authMgr) require.NoError(t, err) swSp, err := swcommon.NewStakeWiseServiceProvider(modSp, swSettings) require.NoError(t, err) From cf33d091cd1798ff06317d9c50f9e82ba09a0df7 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 2 Oct 2024 15:18:48 -0400 Subject: [PATCH 2/3] Minor key updates --- go.mod | 6 +++--- go.sum | 12 +++++------ hyperdrive-cli/client/auth.go | 20 +------------------ hyperdrive-cli/client/client.go | 8 +++++--- .../modules/constellation/cs_daemon.tmpl | 4 ++-- .../modules/stakewise/sw_daemon.tmpl | 4 ++-- internal/tests/cfg_test.go | 11 ++++++---- 7 files changed, 26 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 9ca82de..0a3a9e7 100644 --- a/go.mod +++ b/go.mod @@ -15,9 +15,9 @@ require ( github.com/goccy/go-json v0.10.3 github.com/mholt/archiver/v4 v4.0.0-alpha.8 github.com/mitchellh/go-homedir v1.1.0 - github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d - github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4 - github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f + github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002183331-b9b94bf2218f + github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002190845-1a9ed88f4627 + github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002183435-c4cb9515df86 github.com/nodeset-org/osha v0.3.1-0.20240927160812-d66358d4e091 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/rivo/tview v0.0.0-20230208211350-7dfff1ce7854 // DO NOT UPGRADE diff --git a/go.sum b/go.sum index fc1142d..5ef0016 100644 --- a/go.sum +++ b/go.sum @@ -444,12 +444,12 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d h1:dCoRAdCOw7Ow/mnPupF+/klClG097TFfF9913AQG+dw= -github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002073727-0d956e28557d/go.mod h1:0LcBrdrHkkAs3m7bFRIg9Fb5HbBJazJE3lvgy+QbST8= -github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4 h1:sBdg5zBUwDtjNYfmx8PxvvFWiSKsQSiBKN9ZsJZWib0= -github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002073218-07357eb81ca4/go.mod h1:VXYiN0ZrXbeNALJLa0sin4AzlSrFuGH8gW1YSywoVoI= -github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f h1:OCJ9aniDFD5vR1Y6kcZZo4HzORNbISfjPF5QslyRY3Y= -github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002074720-5fa69604ea9f/go.mod h1:hGpWV7iJwpJg/8pbQnv3t6oGWoMZBHyeY24btNDP324= +github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002183331-b9b94bf2218f h1:uy8P5wxv5lBEPurP3OlaCKMaq+0bw7j/lYtAnD7TM7c= +github.com/nodeset-org/hyperdrive-constellation v1.0.0-b1.0.20241002183331-b9b94bf2218f/go.mod h1:Qf6r3WnPqaxgZI9L/9SYQZnjEIv9+OLEF0VnjzElziU= +github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002190845-1a9ed88f4627 h1:7Gj61zC4/+ZHd94QHq7pz/82PKto+5C3LPeZolEeIN0= +github.com/nodeset-org/hyperdrive-daemon v1.1.0-b1.0.20241002190845-1a9ed88f4627/go.mod h1:VXYiN0ZrXbeNALJLa0sin4AzlSrFuGH8gW1YSywoVoI= +github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002183435-c4cb9515df86 h1:Sf/NTZN3u23+fgdMVR40Ewf8lTFEUfxBonAQ05670W4= +github.com/nodeset-org/hyperdrive-stakewise v1.1.0-b1.0.20241002183435-c4cb9515df86/go.mod h1:ZeMwsXDZWB3U2N8H2QqtMUBO/JbCYS2VCSyptxHZeNM= github.com/nodeset-org/nodeset-client-go v1.0.1-0.20240927160821-e348e05e2363 h1:iivCknAFZlpxPwbIDjPc9E2bnj55c2STrXT9MvuMzQM= github.com/nodeset-org/nodeset-client-go v1.0.1-0.20240927160821-e348e05e2363/go.mod h1:slpwejkJ/vYU9SKA3SYw4hIPJLzDUeQxcx+Cm04kkIA= github.com/nodeset-org/osha v0.3.1-0.20240927160812-d66358d4e091 h1:oAs4/Yx4jnsNdWh3vTKum1sXC8VCvsY1H2VFSRRkgjc= diff --git a/hyperdrive-cli/client/auth.go b/hyperdrive-cli/client/auth.go index 9e257d6..a88822c 100644 --- a/hyperdrive-cli/client/auth.go +++ b/hyperdrive-cli/client/auth.go @@ -23,28 +23,15 @@ var ( // Create the metrics and modules folders, and deploy the config templates for Prometheus and Grafana func (c *HyperdriveClient) GenerateDaemonAuthKeys(config *GlobalConfig) error { - // Make sure the secrets path exists - secretsDirPath := filepath.Join(c.Context.UserDirPath, hdconfig.SecretsDir) - modulesDirPath := filepath.Join(secretsDirPath, hdconfig.ModulesName) - err := os.MkdirAll(modulesDirPath, authDirMode) - if err != nil { - return fmt.Errorf("error creating secrets and modules directories [%s]: %w", modulesDirPath, err) - } - // Create the API key for the Hyperdrive daemon hdApiKeyPath := filepath.Join(c.Context.UserDirPath, hdApiKeyRelPath) - err = auth.GenerateAuthKeyIfNotPresent(hdApiKeyPath, auth.DefaultKeyLength) + err := auth.GenerateAuthKeyIfNotPresent(hdApiKeyPath, auth.DefaultKeyLength) if err != nil { return fmt.Errorf("error generating Hyperdrive daemon API key: %w", err) } // Create the API key for the StakeWise module if enabled if config.StakeWise.Enabled.Value { - swDirPath := filepath.Join(modulesDirPath, swconfig.ModuleName) - err := os.MkdirAll(swDirPath, authDirMode) - if err != nil { - return fmt.Errorf("error creating StakeWise API key module directory [%s]: %w", swDirPath, err) - } swApiKeyPath := filepath.Join(c.Context.UserDirPath, swApiKeyRelPath) err = auth.GenerateAuthKeyIfNotPresent(swApiKeyPath, auth.DefaultKeyLength) if err != nil { @@ -54,11 +41,6 @@ func (c *HyperdriveClient) GenerateDaemonAuthKeys(config *GlobalConfig) error { // Create the API key for the Constellation module if enabled if config.Constellation.Enabled.Value { - csDirPath := filepath.Join(modulesDirPath, csconfig.ModuleName) - err := os.MkdirAll(csDirPath, authDirMode) - if err != nil { - return fmt.Errorf("error creating Constellation API key module directory [%s]: %w", csDirPath, err) - } csApiKeyPath := filepath.Join(c.Context.UserDirPath, csApiKeyRelPath) err = auth.GenerateAuthKeyIfNotPresent(csApiKeyPath, auth.DefaultKeyLength) if err != nil { diff --git a/hyperdrive-cli/client/client.go b/hyperdrive-cli/client/client.go index b152e3c..ee364e6 100644 --- a/hyperdrive-cli/client/client.go +++ b/hyperdrive-cli/client/client.go @@ -29,6 +29,8 @@ const ( BackupSettingsFile string = "user-settings-backup.yml" terminalLogColor color.Attribute = color.FgHiYellow + + cliIssuer string = "hd-cli" ) // Hyperdrive client @@ -104,7 +106,7 @@ func NewHyperdriveClientFromHyperdriveCtx(hdCtx *context.HyperdriveContext) (*Hy // Create the auth manager authPath := filepath.Join(hdCtx.UserDirPath, hdApiKeyRelPath) - authMgr := auth.NewAuthorizationManager(authPath) + authMgr := auth.NewAuthorizationManager(authPath, cliIssuer, auth.DefaultRequestLifespan) // Create the API client hdClient.Api = client.NewApiClient(url, logger, tracer, authMgr) @@ -158,7 +160,7 @@ func NewStakewiseClientFromHyperdriveCtx(hdCtx *context.HyperdriveContext, hdCli // Create the auth manager authPath := filepath.Join(hdCtx.UserDirPath, swApiKeyRelPath) - authMgr := auth.NewAuthorizationManager(authPath) + authMgr := auth.NewAuthorizationManager(authPath, cliIssuer, auth.DefaultRequestLifespan) // Create the API client swClient.Api = swclient.NewApiClient(url, logger, tracer, authMgr) @@ -206,7 +208,7 @@ func NewConstellationClientFromCtx(c *cli.Context, hdClient *HyperdriveClient) ( // Create the auth manager authPath := filepath.Join(hdCtx.UserDirPath, csApiKeyRelPath) - authMgr := auth.NewAuthorizationManager(authPath) + authMgr := auth.NewAuthorizationManager(authPath, cliIssuer, auth.DefaultRequestLifespan) // Create the API client csClient.Api = csclient.NewApiClient(url, logger, tracer, authMgr) diff --git a/install/deploy/templates/modules/constellation/cs_daemon.tmpl b/install/deploy/templates/modules/constellation/cs_daemon.tmpl index febbe69..7f16f79 100644 --- a/install/deploy/templates/modules/constellation/cs_daemon.tmpl +++ b/install/deploy/templates/modules/constellation/cs_daemon.tmpl @@ -31,9 +31,9 @@ services: - --port - "{{.Constellation.ApiPort}}" - --api-key - - "{{.Hyperdrive.GetUserDirectory}}//{{.ConstellationApiKeyPath}}" + - "{{.Hyperdrive.GetUserDirectory}}/{{.ConstellationApiKeyPath}}" - --hd-api-key - - "{{.Hyperdrive.GetUserDirectory}}//{{.HyperdriveApiKeyPath}}" + - "{{.Hyperdrive.GetUserDirectory}}/{{.HyperdriveApiKeyPath}}" networks: - net {{- range $network := .Hyperdrive.GetAdditionalDockerNetworks}} diff --git a/install/deploy/templates/modules/stakewise/sw_daemon.tmpl b/install/deploy/templates/modules/stakewise/sw_daemon.tmpl index 21ca21b..54d48ae 100644 --- a/install/deploy/templates/modules/stakewise/sw_daemon.tmpl +++ b/install/deploy/templates/modules/stakewise/sw_daemon.tmpl @@ -31,9 +31,9 @@ services: - --port - "{{.StakeWise.ApiPort}}" - --api-key - - "{{.Hyperdrive.GetUserDirectory}}//{{.StakeWiseApiKeyPath}}" + - "{{.Hyperdrive.GetUserDirectory}}/{{.StakeWiseApiKeyPath}}" - --hd-api-key - - "{{.Hyperdrive.GetUserDirectory}}//{{.HyperdriveApiKeyPath}}" + - "{{.Hyperdrive.GetUserDirectory}}/{{.HyperdriveApiKeyPath}}" networks: - net {{- range $network := .Hyperdrive.GetAdditionalDockerNetworks}} diff --git a/internal/tests/cfg_test.go b/internal/tests/cfg_test.go index cf25e1b..096b32d 100644 --- a/internal/tests/cfg_test.go +++ b/internal/tests/cfg_test.go @@ -90,9 +90,9 @@ func TestNewConfig_Holesky(t *testing.T) { hdSp, err := hdcommon.NewHyperdriveServiceProvider(hdCtx.UserDirPath, hdCtx.NetworksDir) require.NoError(t, err) hdWg := &sync.WaitGroup{} - authMgr := auth.NewAuthorizationManager("") - authMgr.SetKey([]byte(hdTestApiKey)) - hdServer, err := hdserver.NewServerManager(hdSp, "localhost", 0, hdWg, authMgr) + serverAuthMgr := auth.NewAuthorizationManager("", "server", auth.DefaultRequestLifespan) + serverAuthMgr.SetKey([]byte(hdTestApiKey)) + hdServer, err := hdserver.NewServerManager(hdSp, "localhost", 0, hdWg, serverAuthMgr) require.NoError(t, err) hdServerPort := hdServer.GetPort() defer hdServer.Stop() @@ -105,9 +105,12 @@ func TestNewConfig_Holesky(t *testing.T) { require.NoError(t, err) swSettings, err := hdclient.LoadStakeWiseSettings(hdCtx.NetworksDir) require.NoError(t, err) + + clientAuthMgr := auth.NewAuthorizationManager("", "client", auth.DefaultRequestLifespan) + clientAuthMgr.SetKey([]byte(hdTestApiKey)) modSp, err := modservices.NewModuleServiceProvider(hdApiUrl, swModDir, swconfig.ModuleName, swconfig.ClientLogName, func(hdCfg *hdconfig.HyperdriveConfig) (*swconfig.StakeWiseConfig, error) { return swconfig.NewStakeWiseConfig(hdCfg, swSettings) - }, authMgr) + }, clientAuthMgr) require.NoError(t, err) swSp, err := swcommon.NewStakeWiseServiceProvider(modSp, swSettings) require.NoError(t, err) From d9827e8b79807f1d59856a4540e92c5d86973aa0 Mon Sep 17 00:00:00 2001 From: Joe Clapis Date: Wed, 2 Oct 2024 15:21:31 -0400 Subject: [PATCH 3/3] Linter cleanup --- hyperdrive-cli/client/auth.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/hyperdrive-cli/client/auth.go b/hyperdrive-cli/client/auth.go index a88822c..f034e40 100644 --- a/hyperdrive-cli/client/auth.go +++ b/hyperdrive-cli/client/auth.go @@ -2,7 +2,6 @@ package client import ( "fmt" - "os" "path/filepath" csconfig "github.com/nodeset-org/hyperdrive-constellation/shared/config" @@ -11,10 +10,6 @@ import ( swconfig "github.com/nodeset-org/hyperdrive-stakewise/shared/config" ) -const ( - authDirMode os.FileMode = 0700 -) - var ( hdApiKeyRelPath string = filepath.Join(hdconfig.SecretsDir, hdconfig.DaemonKeyFilename) swApiKeyRelPath string = filepath.Join(hdconfig.SecretsDir, hdconfig.ModulesName, swconfig.ModuleName, hdconfig.DaemonKeyFilename)