diff --git a/orbit/changes/retry-enroll-on-unauth-error b/orbit/changes/retry-enroll-on-unauth-error new file mode 100644 index 0000000000..992f59509b --- /dev/null +++ b/orbit/changes/retry-enroll-on-unauth-error @@ -0,0 +1 @@ +* Orbit now re-enroll when encountering a 401/unauthenticated error when communicating with orbit endpoints on Fleet server diff --git a/orbit/cmd/orbit/orbit.go b/orbit/cmd/orbit/orbit.go index 3ab2d97444..85d3052fb8 100644 --- a/orbit/cmd/orbit/orbit.go +++ b/orbit/cmd/orbit/orbit.go @@ -732,7 +732,7 @@ func getUUID(osqueryPath string) (string, error) { // getOrbitNodeKeyOrEnroll attempts to read the orbit node key if the file exists on disk // otherwise it enrolls the host with Fleet and saves the node key to disk func getOrbitNodeKeyOrEnroll(orbitClient *service.OrbitClient, rootDir string) (string, error) { - nodeKeyFilePath := filepath.Join(rootDir, "secret-orbit-node-key.txt") + nodeKeyFilePath := filepath.Join(rootDir, constant.OrbitNodeKeyFileName) orbitNodeKey, err := ioutil.ReadFile(nodeKeyFilePath) switch { case err == nil: @@ -742,20 +742,16 @@ func getOrbitNodeKeyOrEnroll(orbitClient *service.OrbitClient, rootDir string) ( default: return "", fmt.Errorf("read orbit node key file: %w", err) } - const ( - orbitEnrollMaxRetries = 10 - orbitEnrollRetrySleep = 5 * time.Second - ) - for retries := 0; retries < orbitEnrollMaxRetries; retries++ { + for retries := 0; retries < constant.OrbitEnrollMaxRetries; retries++ { orbitNodeKey, err := enrollAndWriteNodeKeyFile(orbitClient, nodeKeyFilePath) if err != nil { log.Info().Err(err).Msg("enroll failed, retrying") - time.Sleep(orbitEnrollRetrySleep) + time.Sleep(constant.OrbitEnrollRetrySleep) continue } return orbitNodeKey, nil } - return "", fmt.Errorf("orbit node key enroll failed, attempts=%d", orbitEnrollMaxRetries) + return "", fmt.Errorf("orbit node key enroll failed, attempts=%d", constant.OrbitEnrollMaxRetries) } func enrollAndWriteNodeKeyFile(orbitClient *service.OrbitClient, nodeKeyFilePath string) (string, error) { diff --git a/orbit/pkg/constant/constant.go b/orbit/pkg/constant/constant.go index c3e6214800..8395e50943 100644 --- a/orbit/pkg/constant/constant.go +++ b/orbit/pkg/constant/constant.go @@ -1,5 +1,7 @@ package constant +import "time" + const ( // DefaultDirMode is the default file mode to apply to created directories. DefaultDirMode = 0o755 @@ -12,4 +14,10 @@ const ( // We use fleet-desktop as name to properly identify the process when listing // running processes/tasks. DesktopAppExecName = "fleet-desktop" + // OrbitNodeKeyFileName is the filename on disk where we write the orbit node key to + OrbitNodeKeyFileName = "secret-orbit-node-key.txt" + // OrbitEnrollMaxRetries is the max retries when doing an enroll request + OrbitEnrollMaxRetries = 10 + // OrbitEnrollRetrySleep is the time duration to sleep between retries + OrbitEnrollRetrySleep = 5 * time.Second ) diff --git a/orbit/pkg/update/flag_runner.go b/orbit/pkg/update/flag_runner.go index 8b02f53ac4..d12bf4615b 100644 --- a/orbit/pkg/update/flag_runner.go +++ b/orbit/pkg/update/flag_runner.go @@ -95,6 +95,14 @@ func (r *FlagRunner) DoFlagsUpdate() (bool, error) { // next GetConfig from Fleet API flagsJSON, err := r.orbitClient.GetConfig(r.opt.OrbitNodeKey) + // on 401 unauthenticated error, re-enroll and update orbit node key + if errors.Is(err, service.ErrUnauthenticated) { + r.opt.OrbitNodeKey, err = r.updateOrbitNodeKey() + if err != nil { + return false, err + } + return false, nil + } if err != nil { return false, fmt.Errorf("error getting flags from fleet %w", err) } @@ -188,3 +196,23 @@ func readFlagFile(rootDir string) (map[string]string, error) { } return result, nil } + +// updateOrbitNodeKey does re-enrolls by calling the /enroll API and writes the response to disk +func (r *FlagRunner) updateOrbitNodeKey() (string, error) { + for retries := 0; retries < constant.OrbitEnrollMaxRetries; retries++ { + newOrbitNodeKey, err := r.orbitClient.DoEnroll() + if err != nil { + log.Info().Err(err).Msg("re-enroll failed, retrying") + time.Sleep(constant.OrbitEnrollRetrySleep) + continue + } + nodeKeyFilePath := filepath.Join(r.opt.RootDir, constant.OrbitNodeKeyFileName) + if err := os.WriteFile(nodeKeyFilePath, []byte(newOrbitNodeKey), constant.DefaultFileMode); err != nil { + log.Info().Err(err).Msg("failed to write orbit node key to disk") + time.Sleep(constant.OrbitEnrollRetrySleep) + continue + } + return newOrbitNodeKey, nil + } + return "", fmt.Errorf("orbit re-enroll failed, attempts=%d", constant.OrbitEnrollMaxRetries) +}