mirror of
https://github.com/fleetdm/fleet
synced 2026-05-16 21:48:48 +00:00
# Changes - orbit >= 1.38.0, when configured to connect to https://tuf.fleetctl.com (existing fleetd deployments) will now connect to https://updates.fleetdm.com and start using the metadata in path `/opt/orbit/updates-metadata.json`. - orbit >= 1.38.0, when configured to connect to some custom TUF (not Fleet's TUFs) will copy `/opt/orbit/tuf-metadata.json` to `/opt/orbit/updates-metadata.json` (if it doesn't exist) and start using the latter. - fleetctl `4.63.0` will now generate artifacts using https://updates.fleetdm.com by default (or a custom TUF if `--update-url` is set) and generate two (same file) metadata files `/opt/orbit/updates-metadata.json` and the legacy one to support downgrades `/opt/orbit/tuf-metadata.json`. - fleetctl `4.62.0` when configured to use custom TUF (not Fleet's TUF) will generate just the legacy metadata file `/opt/orbit/tuf-metadata.json`. ## User stories See "User stories" in https://github.com/fleetdm/confidential/issues/8488. - [x] Update `update.defaultRootMetadata` and `update.DefaultURL` when the new repository is ready. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files) for more information. - [X] Added/updated tests - [X] Manual QA for all new/changed functionality - For Orbit and Fleet Desktop changes: - [X] Orbit runs on macOS, Linux and Windows. Check if the orbit feature/bugfix should only apply to one platform (`runtime.GOOS`). - [X] Manual QA must be performed in the three main OSs, macOS, Windows and Linux. - [X] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)).
142 lines
4.2 KiB
Go
142 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/fleetdm/fleet/v4/orbit/pkg/constant"
|
|
"github.com/fleetdm/fleet/v4/orbit/pkg/osquery"
|
|
"github.com/fleetdm/fleet/v4/orbit/pkg/update"
|
|
"github.com/fleetdm/fleet/v4/orbit/pkg/update/filestore"
|
|
"github.com/fleetdm/fleet/v4/pkg/secure"
|
|
"github.com/google/uuid"
|
|
"github.com/oklog/run"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var shellCommand = &cli.Command{
|
|
Name: "shell",
|
|
Aliases: []string{"osqueryi"},
|
|
Usage: "Run the osqueryi shell",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "osqueryd-channel",
|
|
Usage: "Channel of osqueryd version to use",
|
|
Value: "stable",
|
|
EnvVars: []string{"ORBIT_OSQUERYD_CHANNEL"},
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "debug",
|
|
Usage: "Enable debug logging",
|
|
EnvVars: []string{"ORBIT_DEBUG"},
|
|
},
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
|
if c.Bool("debug") {
|
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
}
|
|
|
|
if err := secure.MkdirAll(c.String("root-dir"), constant.DefaultDirMode); err != nil {
|
|
return fmt.Errorf("initialize root dir: %w", err)
|
|
}
|
|
|
|
localStore, err := filestore.New(filepath.Join(c.String("root-dir"), update.MetadataFileName))
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("failed to create local metadata store")
|
|
}
|
|
|
|
// Initialize updater and get expected version
|
|
opt := update.DefaultOptions
|
|
|
|
// Override default channel with the provided value.
|
|
opt.Targets.SetTargetChannel(constant.OsqueryTUFTargetName, c.String("osqueryd-channel"))
|
|
|
|
opt.RootDirectory = c.String("root-dir")
|
|
opt.ServerURL = c.String("update-url")
|
|
opt.LocalStore = localStore
|
|
opt.InsecureTransport = c.Bool("insecure")
|
|
|
|
updater, err := update.NewUpdater(opt)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := updater.UpdateMetadata(); err != nil {
|
|
log.Info().Err(err).Msg("failed to update metadata. using saved metadata.")
|
|
}
|
|
osquerydLocalTarget, err := updater.Get(constant.OsqueryTUFTargetName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
osquerydPath := osquerydLocalTarget.ExecPath
|
|
|
|
var g run.Group
|
|
|
|
// We use a suffix on the extension path on Windows
|
|
// because there was an issue when the osqueryd instance ran through
|
|
// `orbit shell` attempted to register the same named pipe name used by
|
|
// the osqueryd instance launched by orbit service.
|
|
extensionPathPostfix := ""
|
|
if runtime.GOOS == "windows" {
|
|
extensionPathPostfix = "-" + uuid.New().String()
|
|
}
|
|
|
|
// We use a different path from the orbit daemon
|
|
// to avoid issues with concurrent accesses to files/databases
|
|
// (RocksDB lock and/or Windows file locking).
|
|
dataPath := filepath.Join(c.String("root-dir"), "shell")
|
|
osqueryDB := filepath.Join(dataPath, "osquery.db")
|
|
opts := []osquery.Option{
|
|
osquery.WithShell(),
|
|
osquery.WithDataPath(dataPath, extensionPathPostfix),
|
|
osquery.WithFlags([]string{"--database_path", osqueryDB}),
|
|
}
|
|
|
|
// Detect if the additional arguments have a positional argument.
|
|
//
|
|
// osqueryi/osqueryd has the following usage:
|
|
// Usage: osqueryi [OPTION]... [SQL STATEMENT]
|
|
additionalArgs := c.Args().Slice()
|
|
singleQueryArg := false
|
|
if len(additionalArgs) > 0 {
|
|
if !strings.HasPrefix(additionalArgs[len(additionalArgs)-1], "--") {
|
|
singleQueryArg = true
|
|
opts = append(opts, osquery.SingleQuery())
|
|
}
|
|
}
|
|
|
|
// Handle additional args after --
|
|
opts = append(opts, osquery.WithFlags(additionalArgs))
|
|
|
|
r, err := osquery.NewRunner(osquerydPath, opts...)
|
|
if err != nil {
|
|
return fmt.Errorf("create osquery runner: %w", err)
|
|
}
|
|
g.Add(r.Execute, r.Interrupt)
|
|
|
|
if !singleQueryArg {
|
|
// We currently start the extension runner when !singleQueryArg
|
|
// because otherwise osquery exits and leaves too quickly,
|
|
// leaving the extension runner waiting for the socket.
|
|
// NOTE(lucas): `--extensions_require` doesn't seem to work with
|
|
// thrift extensions?
|
|
registerExtensionRunner(&g, r.ExtensionSocketPath()+extensionPathPostfix)
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
g.Add(run.SignalHandler(ctx, os.Interrupt, os.Kill))
|
|
|
|
if err := g.Run(); err != nil {
|
|
log.Error().Err(err).Msg("unexpected exit")
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|