Skip to content

Commit

Permalink
Add table to expose autoupdate configuration (#466)
Browse files Browse the repository at this point in the history
kolide_launcher_autoupdate_config table exposes the autoupdate config
via live query or scheduled query when Launcher is running.

Required some refactoring of the options (making struct members public).
  • Loading branch information
zwass authored Apr 18, 2019
1 parent 9c15f44 commit ea189e2
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 102 deletions.
11 changes: 6 additions & 5 deletions cmd/launcher/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@ import (
"github.com/go-kit/kit/log/level"
"github.com/kolide/kit/actor"
"github.com/kolide/launcher/pkg/control"
"github.com/kolide/launcher/pkg/launcher"
"github.com/pkg/errors"
)

func createControl(ctx context.Context, db *bolt.DB, logger log.Logger, opts *options) (*actor.Actor, error) {
func createControl(ctx context.Context, db *bolt.DB, logger log.Logger, opts *launcher.Options) (*actor.Actor, error) {
level.Debug(logger).Log("msg", "creating control client")

controlOpts := []control.Option{
control.WithLogger(logger),
control.WithGetShellsInterval(opts.getShellsInterval),
control.WithGetShellsInterval(opts.GetShellsInterval),
}
if opts.insecureTLS {
if opts.InsecureTLS {
controlOpts = append(controlOpts, control.WithInsecureSkipVerify())
}
if opts.disableControlTLS {
if opts.DisableControlTLS {
controlOpts = append(controlOpts, control.WithDisableTLS())
}
controlClient, err := control.NewControlClient(db, opts.controlServerURL, controlOpts...)
controlClient, err := control.NewControlClient(db, opts.ControlServerURL, controlOpts...)
if err != nil {
return nil, errors.Wrap(err, "creating control client")
}
Expand Down
23 changes: 12 additions & 11 deletions cmd/launcher/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/kolide/kit/actor"
"github.com/kolide/launcher/pkg/launcher"
kolidelog "github.com/kolide/launcher/pkg/log"
"github.com/kolide/launcher/pkg/osquery"
"github.com/kolide/launcher/pkg/osquery/runtime"
Expand All @@ -22,20 +23,20 @@ import (
)

// TODO: the extension, runtime, and client are all kind of entangled here. Untangle the underlying libraries and separate into units
func createExtensionRuntime(ctx context.Context, rootDirectory string, db *bolt.DB, logger log.Logger, launcherClient service.KolideService, opts *options) (
func createExtensionRuntime(ctx context.Context, db *bolt.DB, logger log.Logger, launcherClient service.KolideService, opts *launcher.Options) (
run *actor.Actor,
restart func() error, // restart osqueryd runner
shutdown func() error, // shutdown osqueryd runner
err error,
) {
// read the enroll secret, if either it or the path has been specified
var enrollSecret string
if opts.enrollSecret != "" {
enrollSecret = opts.enrollSecret
} else if opts.enrollSecretPath != "" {
content, err := ioutil.ReadFile(opts.enrollSecretPath)
if opts.EnrollSecret != "" {
enrollSecret = opts.EnrollSecret
} else if opts.EnrollSecretPath != "" {
content, err := ioutil.ReadFile(opts.EnrollSecretPath)
if err != nil {
return nil, nil, nil, errors.Wrapf(err, "could not read enroll_secret_path: %s", opts.enrollSecretPath)
return nil, nil, nil, errors.Wrapf(err, "could not read enroll_secret_path: %s", opts.EnrollSecretPath)
}
enrollSecret = string(bytes.TrimSpace(content))
}
Expand All @@ -44,8 +45,8 @@ func createExtensionRuntime(ctx context.Context, rootDirectory string, db *bolt.
extOpts := osquery.ExtensionOpts{
EnrollSecret: enrollSecret,
Logger: logger,
LoggingInterval: opts.loggingInterval,
RunDifferentialQueriesImmediately: opts.enableInitialRunner,
LoggingInterval: opts.LoggingInterval,
RunDifferentialQueriesImmediately: opts.EnableInitialRunner,
}

// create the extension
Expand All @@ -58,8 +59,8 @@ func createExtensionRuntime(ctx context.Context, rootDirectory string, db *bolt.
osqueryLogger := &kolidelog.OsqueryLogAdapter{Logger: level.Debug(log.With(logger, "component", "osquery"))}

runner := runtime.LaunchUnstartedInstance(
runtime.WithOsquerydBinary(opts.osquerydPath),
runtime.WithRootDirectory(rootDirectory),
runtime.WithOsquerydBinary(opts.OsquerydPath),
runtime.WithRootDirectory(opts.RootDirectory),
runtime.WithConfigPluginFlag("kolide_grpc"),
runtime.WithLoggerPluginFlag("kolide_grpc"),
runtime.WithDistributedPluginFlag("kolide_grpc"),
Expand All @@ -68,7 +69,7 @@ func createExtensionRuntime(ctx context.Context, rootDirectory string, db *bolt.
distributed.NewPlugin("kolide_grpc", ext.GetQueries, ext.WriteResults),
osquerylogger.NewPlugin("kolide_grpc", ext.LogString),
),
runtime.WithOsqueryExtensionPlugins(ktable.LauncherTables(db)...),
runtime.WithOsqueryExtensionPlugins(ktable.LauncherTables(db, opts)...),
runtime.WithStdout(osqueryLogger),
runtime.WithStderr(osqueryLogger),
runtime.WithLogger(logger),
Expand Down
37 changes: 19 additions & 18 deletions cmd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/kolide/kit/logutil"
"github.com/kolide/kit/version"
"github.com/kolide/launcher/pkg/debug"
"github.com/kolide/launcher/pkg/launcher"
"github.com/kolide/launcher/pkg/osquery"
"github.com/kolide/launcher/pkg/osquery/runtime"
"github.com/kolide/launcher/pkg/service"
Expand Down Expand Up @@ -179,9 +180,9 @@ func runSocket(args []string) error {
}

// run the launcher daemon
func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.Logger) error {
func runLauncher(ctx context.Context, cancel func(), opts *launcher.Options, logger log.Logger) error {
// determine the root directory, create one if it's not provided
rootDirectory := opts.rootDirectory
rootDirectory := opts.RootDirectory
if rootDirectory == "" {
rootDirectory = filepath.Join(os.TempDir(), defaultRootDirectory)
if _, err := os.Stat(rootDirectory); os.IsNotExist(err) {
Expand Down Expand Up @@ -209,7 +210,7 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L

// construct the appropriate http client based on security settings
httpClient := http.DefaultClient
if opts.insecureTLS {
if opts.InsecureTLS {
httpClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Expand All @@ -233,14 +234,14 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L

// create the certificate pool
var rootPool *x509.CertPool
if opts.rootPEM != "" {
if opts.RootPEM != "" {
rootPool = x509.NewCertPool()
pemContents, err := ioutil.ReadFile(opts.rootPEM)
pemContents, err := ioutil.ReadFile(opts.RootPEM)
if err != nil {
return errors.Wrapf(err, "reading root certs PEM at path: %s", opts.rootPEM)
return errors.Wrapf(err, "reading root certs PEM at path: %s", opts.RootPEM)
}
if ok := rootPool.AppendCertsFromPEM(pemContents); !ok {
return errors.Errorf("found no valid certs in PEM at path: %s", opts.rootPEM)
return errors.Errorf("found no valid certs in PEM at path: %s", opts.RootPEM)
}
}
// create a rungroup for all the actors we create to allow for easy start/stop
Expand All @@ -266,9 +267,9 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L

var client service.KolideService
{
switch opts.transport {
switch opts.Transport {
case "grpc":
grpcConn, err := service.DialGRPC(opts.kolideServerURL, opts.insecureTLS, opts.insecureTransport, opts.certPins, rootPool, logger)
grpcConn, err := service.DialGRPC(opts.KolideServerURL, opts.InsecureTLS, opts.InsecureTransport, opts.CertPins, rootPool, logger)
if err != nil {
return errors.Wrap(err, "dialing grpc server")
}
Expand All @@ -277,14 +278,14 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L
queryTargeter := createQueryTargetUpdater(logger, db, grpcConn)
runGroup.Add(queryTargeter.Execute, queryTargeter.Interrupt)
case "jsonrpc":
client = service.NewJSONRPCClient(opts.kolideServerURL, opts.insecureTLS, opts.insecureTransport, opts.certPins, rootPool, logger)
client = service.NewJSONRPCClient(opts.KolideServerURL, opts.InsecureTLS, opts.InsecureTransport, opts.CertPins, rootPool, logger)
default:
return errors.New("invalid transport option selected")
}
}

// create the osquery extension for launcher
extension, runnerRestart, runnerShutdown, err := createExtensionRuntime(ctx, rootDirectory, db, logger, client, opts)
extension, runnerRestart, runnerShutdown, err := createExtensionRuntime(ctx, db, logger, client, opts)
if err != nil {
return errors.Wrap(err, "create extension with runtime")
}
Expand All @@ -298,7 +299,7 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L
)

// If the control server has been opted-in to, run it
if opts.control {
if opts.Control {
control, err := createControl(ctx, db, logger, opts)
if err != nil {
return errors.Wrap(err, "create control actor")
Expand All @@ -311,20 +312,20 @@ func runLauncher(ctx context.Context, cancel func(), opts *options, logger log.L
}

// If the autoupdater is enabled, enable it for both osquery and launcher
if opts.autoupdate {
if opts.Autoupdate {
config := &updaterConfig{
Logger: logger,
RootDirectory: rootDirectory,
AutoupdateInterval: opts.autoupdateInterval,
UpdateChannel: opts.updateChannel,
NotaryURL: opts.notaryServerURL,
MirrorURL: opts.mirrorServerURL,
AutoupdateInterval: opts.AutoupdateInterval,
UpdateChannel: opts.UpdateChannel,
NotaryURL: opts.NotaryServerURL,
MirrorURL: opts.MirrorServerURL,
HTTPClient: httpClient,
SigChannel: sigChannel,
}

// create an updater for osquery
osqueryUpdater, err := createUpdater(ctx, opts.osquerydPath, runnerRestart, logger, config)
osqueryUpdater, err := createUpdater(ctx, opts.OsquerydPath, runnerRestart, logger, config)
if err != nil {
return errors.Wrap(err, "create osquery updater")
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/launcher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func main() {
os.Exit(1)
}

logger = logutil.NewServerLogger(opts.debug)
logger = logutil.NewServerLogger(opts.Debug)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down
78 changes: 25 additions & 53 deletions cmd/launcher/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,19 @@ import (

"github.com/kolide/kit/version"
"github.com/kolide/launcher/pkg/autoupdate"
"github.com/kolide/launcher/pkg/launcher"
"github.com/peterbourgon/ff"
"github.com/pkg/errors"
)

// options is the set of configurable options that may be set when launching this
// program
type options struct {
kolideServerURL string
enrollSecret string
enrollSecretPath string
rootDirectory string
osquerydPath string
certPins [][]byte
rootPEM string
loggingInterval time.Duration
enableInitialRunner bool
transport string

control bool
controlServerURL string
getShellsInterval time.Duration

autoupdate bool
debug bool
disableControlTLS bool
insecureTLS bool
insecureTransport bool
notaryServerURL string
mirrorServerURL string
autoupdateInterval time.Duration
updateChannel autoupdate.UpdateChannel
}

const (
defaultRootDirectory = "launcher-root"
)

// parseOptions parses the options that may be configured via command-line flags
// and/or environment variables, determines order of precedence and returns a
// typed struct of options for further application use
func parseOptions(args []string) (*options, error) {
func parseOptions(args []string) (*launcher.Options, error) {
flagset := flag.NewFlagSet("launcher", flag.ExitOnError)
flagset.Usage = func() { usage(flagset) }

Expand Down Expand Up @@ -140,29 +112,29 @@ func parseOptions(args []string) (*options, error) {
return nil, err
}

opts := &options{
kolideServerURL: *flKolideServerURL,
transport: *flTransport,
control: *flControl,
controlServerURL: *flControlServerURL,
getShellsInterval: *flGetShellsInterval,
enrollSecret: *flEnrollSecret,
enrollSecretPath: *flEnrollSecretPath,
rootDirectory: *flRootDirectory,
osquerydPath: osquerydPath,
certPins: certPins,
rootPEM: *flRootPEM,
loggingInterval: *flLoggingInterval,
enableInitialRunner: *flInitialRunner,
autoupdate: *flAutoupdate,
debug: *flDebug,
disableControlTLS: *flDisableControlTLS,
insecureTLS: *flInsecureTLS,
insecureTransport: *flInsecureTransport,
notaryServerURL: *flNotaryServerURL,
mirrorServerURL: *flMirrorURL,
autoupdateInterval: *flAutoupdateInterval,
updateChannel: updateChannel,
opts := &launcher.Options{
KolideServerURL: *flKolideServerURL,
Transport: *flTransport,
Control: *flControl,
ControlServerURL: *flControlServerURL,
GetShellsInterval: *flGetShellsInterval,
EnrollSecret: *flEnrollSecret,
EnrollSecretPath: *flEnrollSecretPath,
RootDirectory: *flRootDirectory,
OsquerydPath: osquerydPath,
CertPins: certPins,
RootPEM: *flRootPEM,
LoggingInterval: *flLoggingInterval,
EnableInitialRunner: *flInitialRunner,
Autoupdate: *flAutoupdate,
Debug: *flDebug,
DisableControlTLS: *flDisableControlTLS,
InsecureTLS: *flInsecureTLS,
InsecureTransport: *flInsecureTransport,
NotaryServerURL: *flNotaryServerURL,
MirrorServerURL: *flMirrorURL,
AutoupdateInterval: *flAutoupdateInterval,
UpdateChannel: updateChannel,
}
return opts, nil
}
Expand Down
25 changes: 13 additions & 12 deletions cmd/launcher/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/kolide/kit/stringutil"
"github.com/kolide/launcher/pkg/launcher"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -80,7 +81,7 @@ func TestOptionsFromFile(t *testing.T) {
require.Equal(t, expectedOpts, opts)
}

func getArgsAndResponse() (map[string]string, *options) {
func getArgsAndResponse() (map[string]string, *launcher.Options) {
randomHostname := fmt.Sprintf("%s.example.com", stringutil.RandomString(8))
randomInt := rand.Intn(1024)

Expand All @@ -94,17 +95,17 @@ func getArgsAndResponse() (map[string]string, *options) {
"-transport": "grpc",
}

opts := &options{
control: true,
osquerydPath: "/dev/null",
kolideServerURL: randomHostname,
getShellsInterval: 3 * time.Second,
loggingInterval: time.Duration(randomInt) * time.Second,
autoupdateInterval: 48 * time.Hour,
notaryServerURL: "https://notary.kolide.co",
mirrorServerURL: "https://dl.kolide.co",
updateChannel: "stable",
transport: "grpc",
opts := &launcher.Options{
Control: true,
OsquerydPath: "/dev/null",
KolideServerURL: randomHostname,
GetShellsInterval: 3 * time.Second,
LoggingInterval: time.Duration(randomInt) * time.Second,
AutoupdateInterval: 48 * time.Hour,
NotaryServerURL: "https://notary.kolide.co",
MirrorServerURL: "https://dl.kolide.co",
UpdateChannel: "stable",
Transport: "grpc",
}

return args, opts
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ require (
github.com/cenkalti/backoff v2.0.0+incompatible // indirect
github.com/client9/misspell v0.3.4
github.com/cloudflare/cfssl v0.0.0-20181102015659-ea4033a214e7 // indirect
github.com/davecgh/go-spew v1.1.1
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f // indirect
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
Expand Down
Loading

0 comments on commit ea189e2

Please sign in to comment.