Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove autoloaded extensions #1603

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion cmd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ func runLauncher(ctx context.Context, cancel func(), multiSlogger, systemMultiSl
kolidelog.WithLevel(slog.LevelInfo),
)),
osqueryruntime.WithAugeasLensFunction(augeas.InstallLenses),
osqueryruntime.WithAutoloadedExtensions(k.AutoloadedExtensions()...),
osqueryruntime.WithUpdateDirectory(k.UpdateDirectory()),
osqueryruntime.WithUpdateChannel(k.UpdateChannel()),
osqueryruntime.WithConfigPluginFlag("kolide_grpc"),
Expand Down
4 changes: 0 additions & 4 deletions ee/agent/flags/flag_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,6 @@ func (fc *FlagController) overrideFlag(key keys.FlagKey, duration time.Duration,
fc.overrides[key].Start(key, value, duration, overrideExpired)
}

func (fc *FlagController) AutoloadedExtensions() []string {
return fc.cmdLineOpts.AutoloadedExtensions
}

func (fc *FlagController) SetKolideServerURL(url string) error {
return fc.setControlServerValue(keys.KolideServerURL, []byte(url))
}
Expand Down
4 changes: 0 additions & 4 deletions ee/agent/types/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ type Flags interface {
// Registers an observer to receive messages when the specified keys change.
RegisterChangeObserver(observer FlagsChangeObserver, flagKeys ...keys.FlagKey)

// AutoloadedExtensions to load with osquery, expected to be in same
// directory as launcher binary.
AutoloadedExtensions() []string

// KolideServerURL is the URL of the management server to connect to.
SetKolideServerURL(url string) error
KolideServerURL() string
Expand Down
16 changes: 0 additions & 16 deletions ee/agent/types/mocks/flags.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions ee/agent/types/mocks/knapsack.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions pkg/autoupdate/findnew.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func FindNewest(ctx context.Context, fullBinaryPath string, opts ...newestOption
func getUpdateDir(fullBinaryPath string) string {
if strings.Contains(fullBinaryPath, ".app") {
binary := filepath.Base(fullBinaryPath)
return filepath.Join(FindBaseDir(fullBinaryPath), binary+updateDirSuffix)
return filepath.Join(findBaseDir(fullBinaryPath), binary+updateDirSuffix)
}

// These are cases that shouldn't really happen. But, this is
Expand Down Expand Up @@ -317,10 +317,10 @@ func getPossibleUpdates(ctx context.Context, updateDir, binaryName string) ([]st
return possibleUpdates, nil
}

// FindBaseDir takes a binary path, that may or may not include the
// findBaseDir takes a binary path, that may or may not include the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this, and anything else in the FindNewest?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we fall back to the legacy autoupdate library currently if there's nothing in the new library. We can definitely get rid of that at some point, but I wasn't in a rush to rip that part out as quickly.

// update directory, and returns the base directory. It's used by the
// launcher runtime in finding the various binaries.
func FindBaseDir(path string) string {
func findBaseDir(path string) string {
if path == "" {
return ""
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/autoupdate/findnew_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestFindBaseDir(t *testing.T) {
}

for _, tt := range tests {
require.Equal(t, tt.out, FindBaseDir(tt.in), "input: %s", tt.in)
require.Equal(t, tt.out, findBaseDir(tt.in), "input: %s", tt.in)
}
}

Expand Down
9 changes: 3 additions & 6 deletions pkg/launcher/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ import (

// Options is the set of options that may be configured for Launcher.
type Options struct {
// AutoloadedExtensions to load with osquery, expected to be in same
// directory as launcher binary.
AutoloadedExtensions []string
// KolideServerURL is the URL of the management server to connect to.
KolideServerURL string
// KolideHosted true if using Kolide SaaS settings
Expand Down Expand Up @@ -205,7 +202,6 @@ func ParseOptions(subcommandName string, args []string) (*Options, error) {

var (
// Primary options
flAutoloadedExtensions ArrayFlags
flCertPins = flagset.String("cert_pins", "", "Comma separated, hex encoded SHA256 hashes of pinned subject public key info")
flControlRequestInterval = flagset.Duration("control_request_interval", 60*time.Second, "The interval at which the control server requests will be made")
flEnrollSecret = flagset.String("enroll_secret", "", "The enroll secret that is used in your environment")
Expand Down Expand Up @@ -270,7 +266,9 @@ func ParseOptions(subcommandName string, args []string) (*Options, error) {
)

flagset.Var(&flOsqueryFlags, "osquery_flag", "Flags to pass to osquery (possibly overriding Launcher defaults)")
flagset.Var(&flAutoloadedExtensions, "autoloaded_extension", "extension paths to autoload, filename without path may be used in same directory as launcher")

// Deprecated array
flagset.Var(&ArrayFlags{}, "autoloaded_extension", "DEPRECATED")

ffOpts := []ff.Option{
ff.WithConfigFileFlag("config"),
Expand Down Expand Up @@ -393,7 +391,6 @@ func ParseOptions(subcommandName string, args []string) (*Options, error) {
LocalDevelopmentPath: *flLocalDevelopmentPath,
TraceIngestServerURL: *flTraceIngestServerURL,
DisableTraceIngestTLS: *flDisableIngestTLS,
AutoloadedExtensions: flAutoloadedExtensions,
IAmBreakingEELicense: *flIAmBreakingEELicense,
InsecureTLS: *flInsecureTLS,
InsecureTransport: *flInsecureTransport,
Expand Down
12 changes: 5 additions & 7 deletions pkg/launcher/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,12 +233,11 @@ func getArgsAndResponse() (map[string]string, *Options) {

// includes both `-` and `--` for variety.
args := map[string]string{
"--hostname": randomHostname,
"-autoupdate_interval": "48h",
"-logging_interval": fmt.Sprintf("%ds", randomInt),
"-osqueryd_path": windowsAddExe("/dev/null"),
"-transport": "grpc",
"-autoloaded_extension": "some-extension.ext",
"--hostname": randomHostname,
"-autoupdate_interval": "48h",
"-logging_interval": fmt.Sprintf("%ds", randomInt),
"-osqueryd_path": windowsAddExe("/dev/null"),
"-transport": "grpc",
}

opts := &Options{
Expand All @@ -260,7 +259,6 @@ func getArgsAndResponse() (map[string]string, *Options) {
OsqueryHealthcheckStartupDelay: 10 * time.Minute,
Transport: "grpc",
UpdateChannel: "stable",
AutoloadedExtensions: []string{"some-extension.ext"},
DelayStart: 0 * time.Second,
WatchdogEnabled: false,
WatchdogDelaySec: 120,
Expand Down
49 changes: 1 addition & 48 deletions pkg/osquery/runtime/osqueryinstance.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/go-kit/kit/log/level"
"github.com/kolide/launcher/ee/agent"
"github.com/kolide/launcher/ee/agent/types"
"github.com/kolide/launcher/pkg/autoupdate"
"github.com/kolide/launcher/pkg/backoff"
"github.com/kolide/launcher/pkg/osquery/runtime/history"
"github.com/kolide/launcher/pkg/traces"
Expand Down Expand Up @@ -214,14 +213,6 @@ func WithAugeasLensFunction(f func(dir string) error) OsqueryInstanceOption {
}
}

// WithAutoloadedExtensions defines a list of extensions to load
// via the osquery autoloading.
func WithAutoloadedExtensions(extensions ...string) OsqueryInstanceOption {
return func(i *OsqueryInstance) {
i.opts.autoloadedExtensions = append(i.opts.autoloadedExtensions, extensions...)
}
}

func WithKnapsack(k types.Knapsack) OsqueryInstanceOption {
return func(i *OsqueryInstance) {
i.knapsack = k
Expand Down Expand Up @@ -317,7 +308,6 @@ type osqueryOptions struct {
configPluginFlag string
distributedPluginFlag string
extensionPlugins []osquery.OsqueryPlugin
autoloadedExtensions []string
extensionSocketPath string
enrollSecretPath string
loggerPluginFlag string
Expand All @@ -344,7 +334,7 @@ func (o osqueryOptions) requiredExtensions() []string {
extensionsMap := make(map[string]bool)
requiredExtensions := make([]string, 0)

for _, extension := range append([]string{o.loggerPluginFlag, o.configPluginFlag, o.distributedPluginFlag}, o.autoloadedExtensions...) {
for _, extension := range []string{o.loggerPluginFlag, o.configPluginFlag, o.distributedPluginFlag} {
// skip the osquery build-ins, since requiring them will cause osquery to needlessly wait.
if extension == "tls" {
continue
Expand Down Expand Up @@ -384,7 +374,6 @@ type osqueryFilePaths struct {
databasePath string
extensionAutoloadPath string
extensionSocketPath string
extensionPaths []string
pidfilePath string
}

Expand All @@ -409,7 +398,6 @@ func calculateOsqueryPaths(opts osqueryOptions) (*osqueryFilePaths, error) {
augeasPath: filepath.Join(opts.rootDirectory, "augeas-lenses"),
extensionSocketPath: extensionSocketPath,
extensionAutoloadPath: extensionAutoloadPath,
extensionPaths: make([]string, len(opts.autoloadedExtensions)),
}

osqueryAutoloadFile, err := os.Create(extensionAutoloadPath)
Expand All @@ -418,41 +406,6 @@ func calculateOsqueryPaths(opts osqueryOptions) (*osqueryFilePaths, error) {
}
defer osqueryAutoloadFile.Close()

if len(opts.autoloadedExtensions) == 0 {
return osqueryFilePaths, nil
}

// Determine the path to the extension
exPath, err := os.Executable()
if err != nil {
return nil, fmt.Errorf("finding path of launcher executable: %w", err)
}

for index, extension := range opts.autoloadedExtensions {
// first see if we just got a file name and check to see if it exists in the executable directory
extensionPath := filepath.Join(autoupdate.FindBaseDir(exPath), extension)

if _, err := os.Stat(extensionPath); err != nil {
// if we got an error, try the raw flag
extensionPath = extension

if _, err := os.Stat(extensionPath); err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("extension path does not exist: %s: %w", extension, err)
} else {
return nil, fmt.Errorf("could not stat extension path: %w", err)
}
}
}

osqueryFilePaths.extensionPaths[index] = extensionPath

_, err := osqueryAutoloadFile.WriteString(fmt.Sprintf("%s\n", extensionPath))
if err != nil {
return nil, fmt.Errorf("writing to autoload file: %w", err)
}
}

return osqueryFilePaths, nil
}

Expand Down
12 changes: 0 additions & 12 deletions pkg/osquery/runtime/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,18 +256,6 @@ func (r *Runner) launchOsqueryInstance() error {
return fmt.Errorf("could not calculate osquery file paths: %w", err)
}

for _, path := range paths.extensionPaths {
// The extensions files should be owned by the process's UID or by root.
// Osquery will refuse to load the extension otherwise.
if err := ensureProperPermissions(o, path); err != nil {
r.slogger.Log(ctx, slog.LevelInfo,
"unable to ensure proper permissions on extension path",
"path", path,
"err", err,
)
}
}

// Populate augeas lenses, if requested
if o.opts.augeasLensFunc != nil {
if err := os.MkdirAll(paths.augeasPath, 0755); err != nil {
Expand Down
31 changes: 0 additions & 31 deletions pkg/osquery/runtime/runtime_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ package runtime

import (
"fmt"
"os"
"os/exec"
"path/filepath"
"syscall"

"github.com/go-kit/kit/log/level"
)

func setpgid() *syscall.SysProcAttr {
Expand All @@ -36,31 +33,3 @@ func platformArgs() []string {
func isExitOk(err error) bool {
return false
}

func ensureProperPermissions(o *OsqueryInstance, path string) error {
fd, err := os.Stat(path)
if err != nil {
return fmt.Errorf("stat-ing path: %w", err)
}
sys := fd.Sys().(*syscall.Stat_t)
isRootOwned := (sys.Uid == 0)
isProcOwned := (sys.Uid == uint32(os.Geteuid()))

if isRootOwned || isProcOwned {
return nil
}

level.Info(o.logger).Log(
"msg", "unsafe permissions detected on path",
"path", path,
)

// chown the path. This could potentially be insecure, since
// we're basically chown-ing whatever is there to root, but a certain
// level of privilege is needed to place something in the launcher root
// directory.
if err = os.Chown(path, os.Getuid(), os.Getgid()); err != nil {
return fmt.Errorf("attempting to chown path: %w", err)
}
return nil
}
4 changes: 0 additions & 4 deletions pkg/osquery/runtime/runtime_helpers_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,3 @@ func isExitOk(err error) bool {
}
return false
}

func ensureProperPermissions(o *OsqueryInstance, path string) error {
return nil
}
46 changes: 0 additions & 46 deletions pkg/osquery/runtime/runtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,52 +101,6 @@ func TestCalculateOsqueryPaths(t *testing.T) {
require.Equal(t, binDir, filepath.Dir(paths.extensionAutoloadPath))
}

func TestCalculateOsqueryPathsWithAutoloadedExtensions(t *testing.T) {
t.Parallel()
binDir, err := getBinDir()
require.NoError(t, err)

extensionPaths := make([]string, 0)

for _, extension := range []string{"extensionInExecDir1", "extensionInExecDir2"} {
// create file at each extension path
extensionPath := filepath.Join(binDir, extension)
require.NoError(t, os.WriteFile(extensionPath, []byte("{}"), 0644))
extensionPaths = append(extensionPaths, extensionPath)
}

nonExecDir := t.TempDir()
for _, extension := range []string{"extensionNotInExecDir1", "extensionNotInExecDir2"} {
// create file at each extension path
extensionPath := filepath.Join(nonExecDir, extension)
require.NoError(t, os.WriteFile(extensionPath, []byte("{}"), 0644))
extensionPaths = append(extensionPaths, extensionPath)
}

paths, err := calculateOsqueryPaths(osqueryOptions{
rootDirectory: binDir,
autoloadedExtensions: []string{"extensionInExecDir1", "extensionInExecDir2", filepath.Join(nonExecDir, "extensionNotInExecDir1"), filepath.Join(nonExecDir, "extensionNotInExecDir2")},
})

require.NoError(t, err)

// ensure that all of our resulting artifact files are in the rootDir that we
// dictated
require.Equal(t, binDir, filepath.Dir(paths.pidfilePath))
require.Equal(t, binDir, filepath.Dir(paths.databasePath))
require.Equal(t, binDir, filepath.Dir(paths.extensionSocketPath))
require.Equal(t, binDir, filepath.Dir(paths.extensionAutoloadPath))

osqueryAutoloadFilePath := filepath.Join(binDir, "osquery.autoload")
// read each line of the autoload file into a string array
bytes, err := os.ReadFile(osqueryAutoloadFilePath)
require.NoError(t, err)
autoloadFileLines := strings.Split(string(bytes), "\n")

// add empty string to extensions path array so it matches the last line of autoloaded file
assert.ElementsMatch(t, append(extensionPaths, ""), autoloadFileLines)
}

func TestCreateOsqueryCommand(t *testing.T) {
t.Parallel()
paths := &osqueryFilePaths{
Expand Down
Loading