From 35e06fa1eeb1970f22aac8389f73061a2fd2c3ec Mon Sep 17 00:00:00 2001 From: Roberto Dip Date: Thu, 27 Apr 2023 10:22:42 -0300 Subject: [PATCH] ensure file permissions of the nudge config file are consistent (#11374) For #11218, In the initial implementation of the feature, we used to launch Nudge as a root, so setting the permissions of the config file to 0600 was okay. As part of the fix for #10044, we now launch Nudge as the current user (which is also recommended in the Nudge wiki), but previous installations of the beta version (probably only Fleeties using Dogfood) still have the configuration file with restrictive permissions, so Nudge wasn't able to read the config when launched as a user. This is kind of hidden because `os.WriteFile` takes a permission arugment, but it's only used if it's writing the file for the first time. --- orbit/changes/11218-nudge-config-permissinos | 1 + orbit/pkg/update/nudge.go | 12 ++++++++++ orbit/pkg/update/nudge_test.go | 23 ++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 orbit/changes/11218-nudge-config-permissinos diff --git a/orbit/changes/11218-nudge-config-permissinos b/orbit/changes/11218-nudge-config-permissinos new file mode 100644 index 0000000000..f22364b548 --- /dev/null +++ b/orbit/changes/11218-nudge-config-permissinos @@ -0,0 +1 @@ +* Fixed an issue preventing Nudge to read the configuration file delivered by Fleet on some installations. This only affects you if Nudge was enabled and configured on a host using Orbit v1.8.0 diff --git a/orbit/pkg/update/nudge.go b/orbit/pkg/update/nudge.go index 32f82e95ac..a45e1fe255 100644 --- a/orbit/pkg/update/nudge.go +++ b/orbit/pkg/update/nudge.go @@ -17,6 +17,7 @@ import ( ) const nudgeConfigFile = "nudge-config.json" +const nudgeConfigFileMode = os.FileMode(constant.DefaultWorldReadableFileMode) // NudgeConfigFetcher is a kind of middleware that wraps an OrbitConfigFetcher and a Runner. // It checks the config supplied by the wrapped OrbitConfigFetcher to detects whether the Fleet @@ -135,6 +136,17 @@ func (n *NudgeConfigFetcher) configure(nudgeCfg fleet.NudgeConfig) error { return err } + // ensure the config file has the right permissions, a call to + // WriteFile preserves existing permissions if the file already exists, + // and previous versions of orbit set the permissions of this file to + // constant.DefaultFileMode. + if fileInfo.Mode() != nudgeConfigFileMode { + log.Info().Msgf("%s config file had wrong permissions (%v) setting permissions to %v", cfgFile, fileInfo.Mode(), nudgeConfigFileMode) + if err := os.Chmod(cfgFile, nudgeConfigFileMode); err != nil { + return fmt.Errorf("ensuring permissions of config file, chmod %q: %w", cfgFile, err) + } + } + // this not only an optimization, but mostly a safeguard: if the file // has been tampered and contains very large contents, we don't // want to load them into memory. diff --git a/orbit/pkg/update/nudge_test.go b/orbit/pkg/update/nudge_test.go index 0a6e09e24b..16ac27d684 100644 --- a/orbit/pkg/update/nudge_test.go +++ b/orbit/pkg/update/nudge_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/fleetdm/fleet/v4/orbit/pkg/constant" "github.com/fleetdm/fleet/v4/server/fleet" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -45,6 +46,7 @@ func (s *nudgeTestSuite) TestNudgeConfigFetcherAddNudge() { Interval: interval, runNudgeFn: runNudgeFn, }) + configPath := filepath.Join(tmpDir, nudgeConfigFile) // nudge is not added to targets if nudge config is not present cfg.NudgeConfig = nil @@ -105,7 +107,7 @@ func (s *nudgeTestSuite) TestNudgeConfigFetcherAddNudge() { gotCfg, err = f.GetConfig() require.NoError(t, err) require.Equal(t, cfg, gotCfg) - configBytes, err := os.ReadFile(filepath.Join(tmpDir, nudgeConfigFile)) + configBytes, err := os.ReadFile(configPath) require.NoError(t, err) var savedConfig fleet.NudgeConfig err = json.Unmarshal(configBytes, &savedConfig) @@ -117,7 +119,24 @@ func (s *nudgeTestSuite) TestNudgeConfigFetcherAddNudge() { gotCfg, err = f.GetConfig() require.NoError(t, err) require.Equal(t, cfg, gotCfg) - configBytes, err = os.ReadFile(filepath.Join(tmpDir, nudgeConfigFile)) + configBytes, err = os.ReadFile(configPath) + require.NoError(t, err) + savedConfig = fleet.NudgeConfig{} + err = json.Unmarshal(configBytes, &savedConfig) + require.NoError(t, err) + require.Equal(t, cfg.NudgeConfig, &savedConfig) + + // config permissions are always validated and set to the right value + err = os.Chmod(configPath, constant.DefaultFileMode) + require.NoError(t, err) + gotCfg, err = f.GetConfig() + require.NoError(t, err) + require.Equal(t, cfg, gotCfg) + fileInfo, err := os.Stat(configPath) + require.NoError(t, err) + require.Equal(t, fileInfo.Mode(), nudgeConfigFileMode) + + configBytes, err = os.ReadFile(configPath) require.NoError(t, err) savedConfig = fleet.NudgeConfig{} err = json.Unmarshal(configBytes, &savedConfig)