mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Allow disabling auto updates in fleetctl package
and orbit
(#4296)
* Add disable-updates flag to fleetctl and orbit * Fix ruleguard execution error on make lint-go * Introduce dev-mode for ease of development of orbit * Add changes file
This commit is contained in:
parent
8e68ec3b96
commit
c641e39ef4
1
changes/issue-3658-orbit-allow-disable-updates
Normal file
1
changes/issue-3658-orbit-allow-disable-updates
Normal file
@ -0,0 +1 @@
|
||||
* Add flag to `fleetctl package` and `orbit` to disable auto updates.
|
@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
@ -286,7 +286,7 @@ func TestApplyPolicies(t *testing.T) {
|
||||
if name == "Team1" {
|
||||
return &fleet.Team{ID: 123}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected team name!")
|
||||
return nil, errors.New("unexpected team name!")
|
||||
}
|
||||
ds.NewActivityFunc = func(ctx context.Context, user *fleet.User, activityType string, details *map[string]interface{}) error {
|
||||
return nil
|
||||
|
@ -88,6 +88,11 @@ func packageCommand() *cli.Command {
|
||||
Value: "stable",
|
||||
Destination: &opt.OrbitChannel,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-updates",
|
||||
Usage: "Disable auto updates on the generated package",
|
||||
Destination: &opt.DisableUpdates,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "update-url",
|
||||
Usage: "URL for update server",
|
||||
|
1
go.mod
1
go.mod
@ -70,6 +70,7 @@ require (
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.17 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
||||
github.com/rotisserie/eris v0.5.1
|
||||
github.com/rs/zerolog v1.20.0
|
||||
|
2
go.sum
2
go.sum
@ -986,6 +986,8 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
|
||||
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.17 h1:L5xf3nifnRIdYe9vyMuY2sDnZHIgQol/fDq74FQz7ZY=
|
||||
github.com/quasilyte/go-ruleguard/dsl v0.3.17/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
|
@ -183,9 +183,26 @@ Press Enter to continue, or Control-c to exit.
|
||||
If you want to run orbit from source directly, you can do the following:
|
||||
|
||||
```sh
|
||||
go run github.com/fleetdm/fleet/v4/orbit/cmd/orbit --root-dir /tmp/orbit -- --flagfile=flagfile.txt --verbose
|
||||
go run github.com/fleetdm/fleet/v4/orbit/cmd/orbit \
|
||||
--dev-mode \
|
||||
--disable-updates \
|
||||
--root-dir /tmp/orbit \
|
||||
--fleet-url https://localhost:8080 \
|
||||
--insecure \
|
||||
--enroll-secret Pz3zC0NMDdZfb3FtqiLgwoexItojrYh/ \
|
||||
-- --verbose
|
||||
```
|
||||
|
||||
Or, using a `flagfile.txt` for osqueryd:
|
||||
```sh
|
||||
go run github.com/fleetdm/fleet/v4/orbit/cmd/orbit \
|
||||
--dev-mode \
|
||||
--disable-updates \
|
||||
--root-dir /tmp/orbit \
|
||||
-- --flagfile=flagfile.txt --verbose
|
||||
```
|
||||
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### Logs
|
||||
|
@ -96,6 +96,16 @@ func main() {
|
||||
Value: "stable",
|
||||
EnvVars: []string{"ORBIT_ORBIT_CHANNEL"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-updates",
|
||||
Usage: "Disables auto updates",
|
||||
EnvVars: []string{"ORBIT_DISABLE_UPDATES"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "dev-mode",
|
||||
Usage: "Runs in development mode",
|
||||
EnvVars: []string{"ORBIT_DEV_MODE"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "Enable debug logging",
|
||||
@ -177,22 +187,35 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("failed to create local metadata store")
|
||||
}
|
||||
|
||||
// Initialize updater and get expected version
|
||||
// Get the default osqueryd path from the installation/configuration.
|
||||
osquerydPath := update.LocalPath(c.String("root-dir"), "osqueryd", c.String("osqueryd-channel"), constant.PlatformName)
|
||||
|
||||
if c.Bool("disable-updates") {
|
||||
log.Info().Msg("running with auto updates disabled")
|
||||
}
|
||||
|
||||
var updater *update.Updater
|
||||
if !c.Bool("disable-updates") ||
|
||||
// When running in dev-mode, even if `disable-updates` is set, fetch osqueryd once as part
|
||||
// of initialization.
|
||||
c.Bool("dev-mode") {
|
||||
// Initialize updater and get expected version of osqueryd.
|
||||
opt := update.DefaultOptions
|
||||
opt.RootDirectory = c.String("root-dir")
|
||||
opt.ServerURL = c.String("update-url")
|
||||
opt.LocalStore = localStore
|
||||
opt.InsecureTransport = c.Bool("insecure")
|
||||
updater, err := update.New(opt)
|
||||
updater, err = update.New(opt)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to create updater: %w", err)
|
||||
}
|
||||
if err := updater.UpdateMetadata(); err != nil {
|
||||
log.Info().Err(err).Msg("failed to update metadata. using saved metadata.")
|
||||
}
|
||||
osquerydPath, err := updater.Get("osqueryd", c.String("osqueryd-channel"))
|
||||
osquerydPath, err = updater.Get("osqueryd", c.String("osqueryd-channel"))
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to get osqueryd target: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Clear leftover files from updates
|
||||
@ -215,6 +238,7 @@ func main() {
|
||||
|
||||
var g run.Group
|
||||
|
||||
if !c.Bool("disable-updates") {
|
||||
updateRunner, err := update.NewRunner(updater, update.RunnerOptions{
|
||||
CheckInterval: 10 * time.Second,
|
||||
Targets: map[string]string{
|
||||
@ -226,8 +250,9 @@ func main() {
|
||||
return err
|
||||
}
|
||||
g.Add(updateRunner.Execute, updateRunner.Interrupt)
|
||||
}
|
||||
|
||||
var options []func(*osquery.Runner) error
|
||||
var options []osquery.Option
|
||||
options = append(options, osquery.WithDataPath(c.String("root-dir")))
|
||||
options = append(options, osquery.WithLogPath(path.Join(c.String("root-dir"), "osquery_log")))
|
||||
|
||||
@ -328,7 +353,7 @@ func main() {
|
||||
osquery.WithFlags([]string{"--tls_server_certs", certPath}),
|
||||
)
|
||||
} else {
|
||||
certPath := filepath.Join(opt.RootDirectory, "certs.pem")
|
||||
certPath := filepath.Join(c.String("root-dir"), "certs.pem")
|
||||
if exists, err := file.Exists(certPath); err == nil && exists {
|
||||
_, err = certificate.LoadPEM(certPath)
|
||||
if err != nil {
|
||||
@ -364,8 +389,11 @@ func main() {
|
||||
// override all other flags and flagfile entries.
|
||||
options = append(options, osquery.WithFlags(c.Args().Slice()))
|
||||
|
||||
// Create an osquery runner with the provided options
|
||||
r, _ := osquery.NewRunner(osquerydPath, options...)
|
||||
// Create an osquery runner with the provided options.
|
||||
r, err := osquery.NewRunner(osquerydPath, options...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create osquery runner: %w", err)
|
||||
}
|
||||
g.Add(r.Execute, r.Interrupt)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
|
@ -3,6 +3,7 @@ package osquery
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -31,8 +32,19 @@ type Runner struct {
|
||||
cancel func()
|
||||
}
|
||||
|
||||
type Option func(*Runner) error
|
||||
|
||||
// NewRunner creates a new osquery runner given the provided functional options.
|
||||
func NewRunner(path string, options ...func(*Runner) error) (*Runner, error) {
|
||||
func NewRunner(path string, options ...Option) (*Runner, error) {
|
||||
switch _, err := os.Stat(path); {
|
||||
case err == nil:
|
||||
// OK
|
||||
case errors.Is(err, os.ErrNotExist):
|
||||
return nil, fmt.Errorf("osqueryd doesn't exist at path %q", path)
|
||||
default:
|
||||
return nil, fmt.Errorf("failed to check for osqueryd file: %w", err)
|
||||
}
|
||||
|
||||
r := &Runner{}
|
||||
|
||||
cmd := exec.Command(path)
|
||||
@ -53,7 +65,7 @@ func NewRunner(path string, options ...func(*Runner) error) (*Runner, error) {
|
||||
}
|
||||
|
||||
// WithFlags adds additional flags to the osqueryd invocation.
|
||||
func WithFlags(flags []string) func(*Runner) error {
|
||||
func WithFlags(flags []string) Option {
|
||||
return func(r *Runner) error {
|
||||
r.cmd.Args = append(r.cmd.Args, flags...)
|
||||
return nil
|
||||
@ -62,7 +74,7 @@ func WithFlags(flags []string) func(*Runner) error {
|
||||
|
||||
// WithEnv adds additional environment variables to the osqueryd invocation.
|
||||
// Inputs should be in the form "KEY=VAL".
|
||||
func WithEnv(env []string) func(*Runner) error {
|
||||
func WithEnv(env []string) Option {
|
||||
return func(r *Runner) error {
|
||||
r.cmd.Env = append(r.cmd.Env, env...)
|
||||
return nil
|
||||
@ -78,7 +90,7 @@ func WithShell() func(*Runner) error {
|
||||
}
|
||||
}
|
||||
|
||||
func WithDataPath(path string) func(*Runner) error {
|
||||
func WithDataPath(path string) Option {
|
||||
return func(r *Runner) error {
|
||||
r.dataPath = path
|
||||
|
||||
@ -96,14 +108,14 @@ func WithDataPath(path string) func(*Runner) error {
|
||||
}
|
||||
|
||||
// WithStderr sets the runner's cmd's stderr to the given writer.
|
||||
func WithStderr(w io.Writer) func(*Runner) error {
|
||||
func WithStderr(w io.Writer) Option {
|
||||
return func(r *Runner) error {
|
||||
r.cmd.Stderr = w
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func WithLogPath(path string) func(*Runner) error {
|
||||
func WithLogPath(path string) Option {
|
||||
return func(r *Runner) error {
|
||||
if err := secure.MkdirAll(path, constant.DefaultDirMode); err != nil {
|
||||
return fmt.Errorf("initialize osquery log path: %w", err)
|
||||
|
@ -196,6 +196,7 @@ ORBIT_UPDATE_URL={{ .UpdateURL }}
|
||||
ORBIT_ORBIT_CHANNEL={{ .OrbitChannel }}
|
||||
ORBIT_OSQUERYD_CHANNEL={{ .OsquerydChannel }}
|
||||
{{ if .Insecure }}ORBIT_INSECURE=true{{ end }}
|
||||
{{ if .DisableUpdates }}ORBIT_DISABLE_UPDATES=true{{ end }}
|
||||
{{ if .FleetURL }}ORBIT_FLEET_URL={{.FleetURL}}{{ end }}
|
||||
{{ if .FleetCertificate }}ORBIT_FLEET_CERTIFICATE=/var/lib/orbit/fleet.pem{{ end }}
|
||||
{{ if .EnrollSecret }}ORBIT_ENROLL_SECRET={{.EnrollSecret}}{{ end }}
|
||||
|
@ -84,6 +84,10 @@ var macosLaunchdTemplate = template.Must(template.New("").Option("missingkey=err
|
||||
<key>ORBIT_FLEET_URL</key>
|
||||
<string>{{ .FleetURL }}</string>
|
||||
{{- end }}
|
||||
{{- if .DisableUpdates }}
|
||||
<key>ORBIT_DISABLE_UPDATES</key>
|
||||
<string>true</string>
|
||||
{{- end }}
|
||||
<key>ORBIT_ORBIT_CHANNEL</key>
|
||||
<string>{{ .OrbitChannel }}</string>
|
||||
<key>ORBIT_OSQUERYD_CHANNEL</key>
|
||||
|
@ -39,6 +39,8 @@ type Options struct {
|
||||
Notarize bool
|
||||
// FleetCertificate is a path to a server certificate to include in the package.
|
||||
FleetCertificate string
|
||||
// DisableUpdates disables auto updates on the generated package.
|
||||
DisableUpdates bool
|
||||
// OrbitChannel is the update channel to use for Orbit.
|
||||
OrbitChannel string
|
||||
// OsquerydChannel is the update channel to use for Osquery (osqueryd).
|
||||
|
@ -53,7 +53,7 @@ var windowsWixTemplate = template.Must(template.New("").Option("missingkey=error
|
||||
ErrorControl="ignore"
|
||||
Start="auto"
|
||||
Type="ownProcess"
|
||||
Arguments='--root-dir "[ORBITROOT]." --log-file "[System64Folder]config\systemprofile\AppData\Local\FleetDM\Orbit\Logs\orbit-osquery.log" {{ if .FleetURL }}--fleet-url "{{ .FleetURL }}"{{ end }} {{ if .FleetCertificate }}--fleet-certificate "[ORBITROOT]fleet.pem"{{ end }} {{ if .EnrollSecret }}--enroll-secret-path "[ORBITROOT]secret.txt"{{ end }} {{if .Insecure }}--insecure{{ end }} {{ if .Debug }}--debug{{ end }} {{ if .UpdateURL }}--update-url "{{ .UpdateURL }}" {{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}"'
|
||||
Arguments='--root-dir "[ORBITROOT]." --log-file "[System64Folder]config\systemprofile\AppData\Local\FleetDM\Orbit\Logs\orbit-osquery.log"{{ if .FleetURL }} --fleet-url "{{ .FleetURL }}"{{ end }}{{ if .FleetCertificate }} --fleet-certificate "[ORBITROOT]fleet.pem"{{ end }}{{ if .EnrollSecret }} --enroll-secret-path "[ORBITROOT]secret.txt"{{ end }}{{if .Insecure }} --insecure{{ end }}{{ if .Debug }} --debug{{ end }}{{ if .UpdateURL }} --update-url "{{ .UpdateURL }}"{{ end }}{{ if .DisableUpdates }} --disable-updates{{ end }} --orbit-channel "{{ .OrbitChannel }}" --osqueryd-channel "{{ .OsquerydChannel }}"'
|
||||
>
|
||||
<util:ServiceConfig
|
||||
FirstFailureActionType="restart"
|
||||
|
@ -125,8 +125,13 @@ func (u *Updater) RepoPath(target, channel string) string {
|
||||
return path.Join(target, u.opt.Platform, channel, target+constant.ExecutableExtension(u.opt.Platform))
|
||||
}
|
||||
|
||||
// LocalPath defines the local file path of a target.
|
||||
func LocalPath(rootDir, target, channel, platform string) string {
|
||||
return filepath.Join(rootDir, binDir, target, platform, channel, target+constant.ExecutableExtension(platform))
|
||||
}
|
||||
|
||||
func (u *Updater) LocalPath(target, channel string) string {
|
||||
return u.pathFromRoot(filepath.Join(binDir, target, u.opt.Platform, channel, target+constant.ExecutableExtension(u.opt.Platform)))
|
||||
return LocalPath(u.opt.RootDirectory, target, channel, u.opt.Platform)
|
||||
}
|
||||
|
||||
// Lookup looks up the provided target in the local target metadata. This should
|
||||
@ -300,13 +305,9 @@ func (u *Updater) Download(repoPath, localPath string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *Updater) pathFromRoot(parts ...string) string {
|
||||
return filepath.Join(append([]string{u.opt.RootDirectory}, parts...)...)
|
||||
}
|
||||
|
||||
func (u *Updater) initializeDirectories() error {
|
||||
for _, dir := range []string{
|
||||
u.pathFromRoot(binDir),
|
||||
filepath.Join(u.opt.RootDirectory, binDir),
|
||||
} {
|
||||
err := secure.MkdirAll(dir, constant.DefaultDirMode)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user