mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Initial CLI and file format for fleetctl
This PR implements a program called `fleetctl` which scaffolds a high level CLI interface which can be used to manage a Fleet server. Configuration is articulated using an intent-based API that resembles the API that is used to configure Kubernetes clusters. The idea here is to use the Kubernetes file format as a pattern to reduce the need for operators to become too intimately familiar with dramatically different file formats. (#1578)
This commit is contained in:
parent
3ed772a251
commit
796e0af8be
11 changed files with 363 additions and 1 deletions
10
Makefile
10
Makefile
|
|
@ -97,9 +97,17 @@ endif
|
|||
.pre-fleet:
|
||||
$(eval APP_NAME = fleet)
|
||||
|
||||
build: .prefix .pre-build .pre-fleet
|
||||
.pre-fleetctl:
|
||||
$(eval APP_NAME = fleetctl)
|
||||
|
||||
build: fleet
|
||||
|
||||
fleet: .prefix .pre-build .pre-fleet
|
||||
go build -i -o build/${OUTPUT} -ldflags ${KIT_VERSION} ./cmd/fleet
|
||||
|
||||
fleetctl: .prefix .pre-build .pre-fleetctl
|
||||
go build -i -o build/fleetctl -ldflags ${KIT_VERSION} ./cmd/fleetctl
|
||||
|
||||
lint-js:
|
||||
eslint frontend --ext .js,.jsx
|
||||
|
||||
|
|
|
|||
80
cmd/fleetctl/fleetctl.go
Normal file
80
cmd/fleetctl/fleetctl.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/kit/log"
|
||||
"github.com/go-kit/kit/log/level"
|
||||
"github.com/kolide/kit/logutil"
|
||||
"github.com/kolide/kit/version"
|
||||
)
|
||||
|
||||
func runVersion(args []string) error {
|
||||
version.PrintFull()
|
||||
return nil
|
||||
}
|
||||
|
||||
func runNoop(args []string) error {
|
||||
fmt.Printf("%+v\n", args)
|
||||
return nil
|
||||
}
|
||||
|
||||
type runFunc func([]string) error
|
||||
type subcommandMap map[string]runFunc
|
||||
type commandMap map[string]subcommandMap
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "fleetctl controls an instance of the Kolide Fleet osquery fleet manager.\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, "Find more information at https://kolide.com/fleet\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, " Usage:\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl [command] [flags]\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, " Commands:\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl query - run a query across your fleet\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl apply - apply a set of osquery configurations\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl edit - edit your complete configuration in an ephemeral editor\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl help - get help on how to define an intent type\n")
|
||||
fmt.Fprintf(os.Stderr, " fleetctl version - print full version information\n")
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
}
|
||||
|
||||
func main() {
|
||||
logger := level.NewFilter(log.NewJSONLogger(os.Stderr), level.AllowDebug())
|
||||
logger = log.With(logger, "ts", log.DefaultTimestampUTC)
|
||||
logger = log.With(logger, "caller", log.DefaultCaller)
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
var run func([]string) error
|
||||
switch strings.ToLower(os.Args[1]) {
|
||||
case "version":
|
||||
run = runVersion
|
||||
case "query":
|
||||
run = runNoop
|
||||
case "edit":
|
||||
run = runNoop
|
||||
case "new":
|
||||
run = runNoop
|
||||
case "apply":
|
||||
run = runNoop
|
||||
case "help":
|
||||
run = runNoop
|
||||
default:
|
||||
usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := run(os.Args[2:]); err != nil {
|
||||
logutil.Fatal(logger, "err", err)
|
||||
}
|
||||
}
|
||||
54
examples/combine.go
Normal file
54
examples/combine.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func walk(f *os.File) func(path string, info os.FileInfo, err error) error {
|
||||
return func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
content, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if _, err := f.WriteString(string(content) + "---\n"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
inputDir := "./examples/config-intent-files"
|
||||
outputFile := "./examples/config-intent.yml"
|
||||
|
||||
if err := os.Truncate(outputFile, 0); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := os.OpenFile(outputFile, os.O_APPEND|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := filepath.Walk(inputDir, walk(f)); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
content, err := ioutil.ReadFile(outputFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(outputFile, []byte(strings.Trim(string(content), "---\n")+"\n"), 0644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
9
examples/config-intent-files/config.yml
Normal file
9
examples/config-intent-files/config.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: config
|
||||
spec:
|
||||
config:
|
||||
- distributed_interval: 3
|
||||
- distributed_tls_max_attempts: 3
|
||||
- logger_plugin: tls
|
||||
- logger_tls_endpoint: /api/v1/osquery/log
|
||||
- logger_tls_period: 10
|
||||
14
examples/config-intent-files/decorators.yml
Normal file
14
examples/config-intent-files/decorators.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: decorators
|
||||
spec:
|
||||
decorators:
|
||||
- name: hostname
|
||||
query: select hostname from system_info;
|
||||
type: interval
|
||||
interval: 10
|
||||
- name: uuid
|
||||
query: select uuid from osquery_info;
|
||||
type: load
|
||||
- name: instance_id
|
||||
query: select instance_id from osquery_info;
|
||||
type: load
|
||||
14
examples/config-intent-files/fim.yml
Normal file
14
examples/config-intent-files/fim.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: fim
|
||||
spec:
|
||||
fim:
|
||||
interval: 500
|
||||
groups:
|
||||
- name: etc
|
||||
paths:
|
||||
- /etc/%%
|
||||
- name: users
|
||||
paths:
|
||||
- /Users/%/Library/%%
|
||||
- /Users/%/Documents/%%
|
||||
|
||||
26
examples/config-intent-files/labels.yml
Normal file
26
examples/config-intent-files/labels.yml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: labels
|
||||
spec:
|
||||
labels:
|
||||
- name: all_hosts
|
||||
query: select 1;
|
||||
- name: macs
|
||||
query: select 1 from os_version where platform = "darwin";
|
||||
- name: ubuntu
|
||||
query: select 1 from os_version where platform = "ubuntu";
|
||||
- name: centos
|
||||
query: select 1 from os_version where platform = "centos";
|
||||
- name: windows
|
||||
query: select 1 from os_version where platform = "windows";
|
||||
- name: pending_updates
|
||||
query: SELECT value from plist where path = "/Library/Preferences/ManagedInstalls.plist" and key = "PendingUpdateCount" and value > "0";
|
||||
platforms:
|
||||
- darwin
|
||||
- name: slack_not_running
|
||||
query: >
|
||||
SELECT * from system_info
|
||||
WHERE NOT EXISTS (
|
||||
SELECT *
|
||||
FROM processes
|
||||
WHERE name LIKE "%Slack%"
|
||||
);
|
||||
21
examples/config-intent-files/packs/osquery-monitoring.yml
Normal file
21
examples/config-intent-files/packs/osquery-monitoring.yml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: pack
|
||||
metadata:
|
||||
name: osquery_monitoring
|
||||
spec:
|
||||
targets:
|
||||
labels:
|
||||
- all_hosts
|
||||
queries:
|
||||
- name: osquery_schedule
|
||||
interval: 7200
|
||||
removed: false
|
||||
description: Report performance publisher health and track event counters.
|
||||
- name: osquery_events
|
||||
interval: 86400
|
||||
removed: false
|
||||
description: Report event publisher health and track event counters.
|
||||
- name: oquery_info
|
||||
interval: 600
|
||||
removed: false
|
||||
description: A heartbeat counter that reports general performance (CPU, memory) and version.
|
||||
6
examples/config-intent-files/queries/processes.yml
Normal file
6
examples/config-intent-files/queries/processes.yml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: query
|
||||
metadata:
|
||||
- name: processes
|
||||
spec:
|
||||
query: select * from processes;
|
||||
17
examples/config-intent-files/queries/queries.yml
Normal file
17
examples/config-intent-files/queries/queries.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: queries
|
||||
spec:
|
||||
queries:
|
||||
- name: launcher_version
|
||||
query: select version from kolide_launcher_info;
|
||||
- name: osquery_version
|
||||
query: select version from osquery_info;
|
||||
- name: osquery_schedule
|
||||
query: select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory, last_executed from osquery_schedule;
|
||||
description: Report performance publisher health and track event counters.
|
||||
- name: osquery_events
|
||||
query: select name, publisher, type, subscriptions, events, active from osquery_events;
|
||||
description: Report event publisher health and track event counters.
|
||||
- name: osquery_info
|
||||
query: select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;
|
||||
description: A heartbeat counter that reports general performance (CPU, memory) and version.
|
||||
113
examples/config-intent.yml
Normal file
113
examples/config-intent.yml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
apiVersion: v1/alpha
|
||||
kind: config
|
||||
spec:
|
||||
config:
|
||||
- distributed_interval: 3
|
||||
- distributed_tls_max_attempts: 3
|
||||
- logger_plugin: tls
|
||||
- logger_tls_endpoint: /api/v1/osquery/log
|
||||
- logger_tls_period: 10
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: decorators
|
||||
spec:
|
||||
decorators:
|
||||
- name: hostname
|
||||
query: select hostname from system_info;
|
||||
type: interval
|
||||
interval: 10
|
||||
- name: uuid
|
||||
query: select uuid from osquery_info;
|
||||
type: load
|
||||
- name: instance_id
|
||||
query: select instance_id from osquery_info;
|
||||
type: load
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: fim
|
||||
spec:
|
||||
fim:
|
||||
interval: 500
|
||||
groups:
|
||||
- name: etc
|
||||
paths:
|
||||
- /etc/%%
|
||||
- name: users
|
||||
paths:
|
||||
- /Users/%/Library/%%
|
||||
- /Users/%/Documents/%%
|
||||
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: labels
|
||||
spec:
|
||||
labels:
|
||||
- name: all_hosts
|
||||
query: select 1;
|
||||
- name: macs
|
||||
query: select 1 from os_version where platform = "darwin";
|
||||
- name: ubuntu
|
||||
query: select 1 from os_version where platform = "ubuntu";
|
||||
- name: centos
|
||||
query: select 1 from os_version where platform = "centos";
|
||||
- name: windows
|
||||
query: select 1 from os_version where platform = "windows";
|
||||
- name: pending_updates
|
||||
query: SELECT value from plist where path = "/Library/Preferences/ManagedInstalls.plist" and key = "PendingUpdateCount" and value > "0";
|
||||
platforms:
|
||||
- darwin
|
||||
- name: slack_not_running
|
||||
query: >
|
||||
SELECT * from system_info
|
||||
WHERE NOT EXISTS (
|
||||
SELECT *
|
||||
FROM processes
|
||||
WHERE name LIKE "%Slack%"
|
||||
);
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: pack
|
||||
metadata:
|
||||
name: osquery_monitoring
|
||||
spec:
|
||||
targets:
|
||||
labels:
|
||||
- all_hosts
|
||||
queries:
|
||||
- name: osquery_schedule
|
||||
interval: 7200
|
||||
removed: false
|
||||
description: Report performance publisher health and track event counters.
|
||||
- name: osquery_events
|
||||
interval: 86400
|
||||
removed: false
|
||||
description: Report event publisher health and track event counters.
|
||||
- name: oquery_info
|
||||
interval: 600
|
||||
removed: false
|
||||
description: A heartbeat counter that reports general performance (CPU, memory) and version.
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: query
|
||||
metadata:
|
||||
- name: processes
|
||||
spec:
|
||||
query: select * from processes;
|
||||
---
|
||||
apiVersion: v1/alpha
|
||||
kind: queries
|
||||
spec:
|
||||
queries:
|
||||
- name: launcher_version
|
||||
query: select version from kolide_launcher_info;
|
||||
- name: osquery_version
|
||||
query: select version from osquery_info;
|
||||
- name: osquery_schedule
|
||||
query: select name, interval, executions, output_size, wall_time, (user_time/executions) as avg_user_time, (system_time/executions) as avg_system_time, average_memory, last_executed from osquery_schedule;
|
||||
description: Report performance publisher health and track event counters.
|
||||
- name: osquery_events
|
||||
query: select name, publisher, type, subscriptions, events, active from osquery_events;
|
||||
description: Report event publisher health and track event counters.
|
||||
- name: osquery_info
|
||||
query: select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid;
|
||||
description: A heartbeat counter that reports general performance (CPU, memory) and version.
|
||||
Loading…
Reference in a new issue