fix: use zerolog for orbit osquery table logging (#20028)
> Related issue: #19886 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Added/updated tests - [x] Manual QA for all new/changed functionality - For Orbit and Fleet Desktop changes: - [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)).
This commit is contained in:
@@ -0,0 +1 @@
|
||||
- Fixes a bug that caused log Orbit's osquery table log output to be inconsistent.
|
||||
@@ -47,9 +47,8 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/groob/plist"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
howett "howett.net/plist"
|
||||
)
|
||||
@@ -70,7 +69,7 @@ type Flattener struct {
|
||||
expandNestedPlist bool
|
||||
includeNestedRaw bool
|
||||
includeNils bool
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
query []string
|
||||
queryKeyDenoter string
|
||||
queryWildcard string
|
||||
@@ -95,11 +94,7 @@ func WithNestedPlist() FlattenOpts {
|
||||
}
|
||||
|
||||
// WithLogger sets the logger to use
|
||||
func WithLogger(logger log.Logger) FlattenOpts {
|
||||
if logger == nil {
|
||||
return func(_ *Flattener) {}
|
||||
}
|
||||
|
||||
func WithLogger(logger zerolog.Logger) FlattenOpts {
|
||||
return func(fl *Flattener) {
|
||||
fl.logger = logger
|
||||
}
|
||||
@@ -132,7 +127,7 @@ func WithQuery(q []string) FlattenOpts {
|
||||
func Flatten(data interface{}, opts ...FlattenOpts) ([]Row, error) {
|
||||
fl := &Flattener{
|
||||
rows: []Row{},
|
||||
logger: log.NewNopLogger(),
|
||||
logger: zerolog.Nop(),
|
||||
queryWildcard: `*`,
|
||||
queryKeyDenoter: `#`,
|
||||
}
|
||||
@@ -142,7 +137,7 @@ func Flatten(data interface{}, opts ...FlattenOpts) ([]Row, error) {
|
||||
}
|
||||
|
||||
if !fl.debugLogging {
|
||||
fl.logger = level.NewFilter(fl.logger, level.AllowInfo())
|
||||
fl.logger = fl.logger.Level(zerolog.InfoLevel)
|
||||
}
|
||||
|
||||
if err := fl.descend([]string{}, data, 0); err != nil {
|
||||
@@ -155,20 +150,19 @@ func Flatten(data interface{}, opts ...FlattenOpts) ([]Row, error) {
|
||||
// descend recurses through a given data structure flattening along the way.
|
||||
func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
queryTerm, isQueryMatched := fl.queryAtDepth(depth)
|
||||
|
||||
logger := log.With(fl.logger,
|
||||
"caller", "descend",
|
||||
"depth", depth,
|
||||
"rows-so-far", len(fl.rows),
|
||||
"query", queryTerm,
|
||||
"path", strings.Join(path, "/"),
|
||||
)
|
||||
logger := fl.logger.With().
|
||||
Str("caller", "descend").
|
||||
Int("depth", depth).
|
||||
Int("rows-so-far", len(fl.rows)).
|
||||
Str("query", queryTerm).
|
||||
Str("path", strings.Join(path, "/")).
|
||||
Logger()
|
||||
|
||||
switch v := data.(type) {
|
||||
case []interface{}:
|
||||
for i, e := range v {
|
||||
pathKey := strconv.Itoa(i)
|
||||
level.Debug(logger).Log("msg", "checking an array", "indexStr", pathKey)
|
||||
logger.Debug().Str("indexStr", pathKey).Msg("checking an array")
|
||||
|
||||
// If the queryTerm starts with
|
||||
// queryKeyDenoter, then we want to rewrite
|
||||
@@ -184,25 +178,25 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
keyQuery := strings.SplitN(strings.TrimPrefix(queryTerm, fl.queryKeyDenoter), "=>", 2)
|
||||
keyName := keyQuery[0]
|
||||
|
||||
innerlogger := log.With(logger, "arraykeyname", keyName)
|
||||
level.Debug(logger).Log("msg", "attempting to coerce array into map")
|
||||
innerlogger := logger.With().Str("arraykeyname", keyName).Logger()
|
||||
logger.Debug().Msg("attempting to coerce array into map")
|
||||
|
||||
e, ok := e.(map[string]interface{})
|
||||
if !ok {
|
||||
level.Debug(innerlogger).Log("msg", "can't coerce into map")
|
||||
innerlogger.Debug().Msg("can't coerce into map")
|
||||
continue
|
||||
}
|
||||
|
||||
// Is keyName in this array?
|
||||
val, ok := e[keyName]
|
||||
if !ok {
|
||||
level.Debug(innerlogger).Log("msg", "keyName not in map")
|
||||
innerlogger.Debug().Msg("keyName not in map")
|
||||
continue
|
||||
}
|
||||
|
||||
pathKey, ok = val.(string)
|
||||
if !ok {
|
||||
level.Debug(innerlogger).Log("msg", "can't coerce pathKey val into string")
|
||||
innerlogger.Debug().Msg("can't coerce pathKey val into string")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -210,7 +204,7 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
}
|
||||
|
||||
if !(isQueryMatched || fl.queryMatchArrayElement(e, i, queryTerm)) {
|
||||
level.Debug(logger).Log("msg", "query not matched")
|
||||
logger.Debug().Msg("query not matched")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -219,7 +213,7 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
}
|
||||
}
|
||||
case map[string]interface{}:
|
||||
level.Debug(logger).Log("msg", "checking a map")
|
||||
logger.Debug().Msg("checking a map")
|
||||
for k, e := range v {
|
||||
// Check that the key name matches. If not, skip this entire
|
||||
// branch of the map
|
||||
@@ -232,7 +226,7 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
}
|
||||
}
|
||||
case []map[string]interface{}:
|
||||
level.Debug(logger).Log("msg", "checking an array of maps")
|
||||
logger.Debug().Msg("checking an array of maps")
|
||||
for i, e := range v {
|
||||
if err := fl.descend(append(path, strconv.Itoa(i)), e, depth+1); err != nil {
|
||||
return fmt.Errorf("flattening array of maps: %w", err)
|
||||
@@ -241,7 +235,7 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
case nil:
|
||||
// Because we want to filter nils out, we do _not_ examine isQueryMatched here
|
||||
if !(fl.queryMatchNil(queryTerm)) {
|
||||
level.Debug(logger).Log("msg", "query not matched")
|
||||
logger.Debug().Msg("query not matched")
|
||||
return nil
|
||||
}
|
||||
fl.rows = append(fl.rows, NewRow(path, ""))
|
||||
@@ -261,7 +255,7 @@ func (fl *Flattener) descend(path []string, data interface{}, depth int) error {
|
||||
// handleStringLike is called when we finally have an object we think
|
||||
// can be converted to a string. It uses the depth to compare against
|
||||
// the query, and returns a stringify'ed value
|
||||
func (fl *Flattener) handleStringLike(logger log.Logger, path []string, v interface{}, depth int) error {
|
||||
func (fl *Flattener) handleStringLike(logger zerolog.Logger, path []string, v interface{}, depth int) error {
|
||||
queryTerm, isQueryMatched := fl.queryAtDepth(depth)
|
||||
|
||||
stringValue, err := stringify(v)
|
||||
@@ -270,7 +264,7 @@ func (fl *Flattener) handleStringLike(logger log.Logger, path []string, v interf
|
||||
}
|
||||
|
||||
if !(isQueryMatched || fl.queryMatchString(stringValue, queryTerm)) {
|
||||
level.Debug(logger).Log("msg", "query not matched")
|
||||
logger.Debug().Msg("query not matched")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -282,12 +276,12 @@ func (fl *Flattener) handleStringLike(logger log.Logger, path []string, v interf
|
||||
// embedded plist. In the case of failures, it falls back to treating
|
||||
// it like a plain string.
|
||||
func (fl *Flattener) descendMaybePlist(path []string, data []byte, depth int) error {
|
||||
logger := log.With(fl.logger,
|
||||
"caller", "descendMaybePlist",
|
||||
"depth", depth,
|
||||
"rows-so-far", len(fl.rows),
|
||||
"path", strings.Join(path, "/"),
|
||||
)
|
||||
logger := fl.logger.With().
|
||||
Str("caller", "descendMaybePlist").
|
||||
Int("depth", depth).
|
||||
Int("rows-so-far", len(fl.rows)).
|
||||
Str("path", strings.Join(path, "/")).
|
||||
Logger()
|
||||
|
||||
// Skip if we're not expanding nested plists
|
||||
if !fl.expandNestedPlist {
|
||||
@@ -300,19 +294,19 @@ func (fl *Flattener) descendMaybePlist(path []string, data []byte, depth int) er
|
||||
}
|
||||
|
||||
// Looks like a plist. Try parsing it
|
||||
level.Debug(logger).Log("msg", "Parsing inner plist")
|
||||
logger.Debug().Msg("Parsing inner plist")
|
||||
|
||||
var innerData interface{}
|
||||
|
||||
if err := plist.Unmarshal(data, &innerData); err != nil {
|
||||
level.Info(logger).Log("msg", "plist parsing failed", "err", err)
|
||||
logger.Info().Err(err).Msg("plist parsing failed")
|
||||
return fl.handleStringLike(logger, path, data, depth)
|
||||
}
|
||||
|
||||
// have a parsed plist. Descend and return from here.
|
||||
if fl.includeNestedRaw {
|
||||
if err := fl.handleStringLike(logger, append(path, "_raw"), data, depth); err != nil {
|
||||
level.Error(logger).Log("msg", "Failed to add _raw key", "err", err)
|
||||
logger.Error().Err(err).Msg("Failed to add _raw key")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,12 +332,12 @@ func (fl *Flattener) queryMatchNil(queryTerm string) bool {
|
||||
// We use `=>` as something that is reasonably intuitive, and not very
|
||||
// likely to occur on it's own. Unfortunately, `==` shows up in base64
|
||||
func (fl *Flattener) queryMatchArrayElement(data interface{}, arrIndex int, queryTerm string) bool {
|
||||
logger := log.With(fl.logger,
|
||||
"caller", "queryMatchArrayElement",
|
||||
"rows-so-far", len(fl.rows),
|
||||
"query", queryTerm,
|
||||
"arrIndex", arrIndex,
|
||||
)
|
||||
logger := fl.logger.With().
|
||||
Str("caller", "queryMatchArrayElement").
|
||||
Int("rows-so-far", len(fl.rows)).
|
||||
Str("query", queryTerm).
|
||||
Int("arrIndex", arrIndex).
|
||||
Logger()
|
||||
|
||||
// strip off the key re-write denotation before trying to match
|
||||
queryTerm = strings.TrimPrefix(queryTerm, fl.queryKeyDenoter)
|
||||
@@ -354,11 +348,11 @@ func (fl *Flattener) queryMatchArrayElement(data interface{}, arrIndex int, quer
|
||||
|
||||
// If the queryTerm is an int, then we expect to match the index
|
||||
if queryIndex, err := strconv.Atoi(queryTerm); err == nil {
|
||||
level.Debug(logger).Log("msg", "using numeric index comparison")
|
||||
logger.Debug().Msg("using numeric index comparison")
|
||||
return queryIndex == arrIndex
|
||||
}
|
||||
|
||||
level.Debug(logger).Log("msg", "checking data type")
|
||||
logger.Debug().Msg("checking data type")
|
||||
|
||||
switch dataCasted := data.(type) {
|
||||
case []interface{}:
|
||||
@@ -407,7 +401,6 @@ func (fl *Flattener) queryMatchStringify(data interface{}, queryTerm string) boo
|
||||
}
|
||||
|
||||
return fl.queryMatchString(stringValue, queryTerm)
|
||||
|
||||
}
|
||||
|
||||
func (fl *Flattener) queryMatchString(v, queryTerm string) bool {
|
||||
|
||||
@@ -7,18 +7,19 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const kernelCheckUtilPath = "/opt/CrowdStrike/falcon-kernel-check"
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
name string
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := []table.ColumnDefinition{
|
||||
table.TextColumn("kernel"),
|
||||
table.IntegerColumn("supported"),
|
||||
@@ -26,9 +27,9 @@ func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
}
|
||||
|
||||
tableName := "falcon_kernel_check"
|
||||
|
||||
t := &Table{
|
||||
logger: log.With(logger, "table", tableName),
|
||||
name: tableName,
|
||||
logger: logger.With().Str("table", tableName).Logger(),
|
||||
}
|
||||
|
||||
return table.NewPlugin(tableName, columns, t.generate)
|
||||
@@ -37,13 +38,13 @@ func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
|
||||
output, err := tablehelpers.Exec(ctx, t.logger, 5, []string{kernelCheckUtilPath}, []string{}, false)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "exec failed", "err", err)
|
||||
t.logger.Info().Str("table", t.name).Err(err).Msg("exec failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
status, err := parseStatus(string(output))
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "Error parsing exec status", "err", err)
|
||||
t.logger.Info().Str("table", t.name).Err(err).Msg("Error parsing exec status")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,8 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -37,21 +36,21 @@ var (
|
||||
defaultOption = strings.Join(allowedOptions, " ")
|
||||
)
|
||||
|
||||
type execFunc func(context.Context, log.Logger, int, []string, []string, bool) ([]byte, error)
|
||||
type execFunc func(context.Context, zerolog.Logger, int, []string, []string, bool) ([]byte, error)
|
||||
|
||||
type falconctlOptionsTable struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
tableName string
|
||||
execFunc execFunc
|
||||
}
|
||||
|
||||
func NewFalconctlOptionTable(logger log.Logger) *table.Plugin {
|
||||
func NewFalconctlOptionTable(logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
table.TextColumn("options"),
|
||||
)
|
||||
|
||||
t := &falconctlOptionsTable{
|
||||
logger: log.With(logger, "table", "falconctl_options"),
|
||||
logger: logger.With().Str("table", "falconctl_options").Logger(),
|
||||
tableName: "falconctl_options",
|
||||
execFunc: tablehelpers.Exec,
|
||||
}
|
||||
@@ -77,7 +76,7 @@ OUTER:
|
||||
for _, option := range options {
|
||||
option = strings.Trim(option, " ")
|
||||
if !optionAllowed(option) {
|
||||
level.Info(t.logger).Log("msg", "requested option not allowed", "option", option)
|
||||
t.logger.Info().Msgf("requested option not allowed: %s", option)
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
@@ -90,14 +89,14 @@ OUTER:
|
||||
|
||||
output, err := t.execFunc(ctx, t.logger, 30, falconctlPaths, args, false)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "exec failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("exec failed")
|
||||
synthesizedData := map[string]string{
|
||||
"_error": fmt.Sprintf("falconctl parse failure: %s", err),
|
||||
}
|
||||
|
||||
flattened, err := dataflatten.Flatten(synthesizedData)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "failure flattening output", "err", err)
|
||||
t.logger.Info().Err(err).Msg("failure flattening output")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -107,7 +106,7 @@ OUTER:
|
||||
|
||||
parsed, err := parseOptions(bytes.NewReader(output))
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "parse failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("parse failed")
|
||||
parsed = map[string]string{
|
||||
"_error": fmt.Sprintf("falconctl parse failure: %s", err),
|
||||
}
|
||||
@@ -121,7 +120,7 @@ OUTER:
|
||||
|
||||
flattened, err := dataflatten.Flatten(parsed, flattenOpts...)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "failure flattening output", "err", err)
|
||||
t.logger.Info().Err(err).Msg("failure flattening output")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ func TestOptionRestrictions(t *testing.T) {
|
||||
var logBytes bytes.Buffer
|
||||
|
||||
testTable := &falconctlOptionsTable{
|
||||
logger: log.NewLogfmtLogger(&logBytes),
|
||||
logger: zerolog.New(zerolog.ConsoleWriter{Out: &logBytes}),
|
||||
execFunc: noopExec,
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func TestOptionRestrictions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func noopExec(_ context.Context, log log.Logger, _ int, _ []string, args []string, _ bool) ([]byte, error) {
|
||||
log.Log("exec", "exec-in-test", "args", strings.Join(args, " "))
|
||||
func noopExec(_ context.Context, log zerolog.Logger, _ int, _ []string, args []string, _ bool) ([]byte, error) {
|
||||
log.Info().Str("args", strings.Join(args, " ")).Msg("exec-in-test")
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
@@ -14,23 +14,22 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
table.TextColumn("passphrase"),
|
||||
table.TextColumn("path"),
|
||||
)
|
||||
|
||||
t := &Table{
|
||||
logger: logger,
|
||||
logger: logger.With().Str("table", "cryptoinfo").Logger(),
|
||||
}
|
||||
|
||||
return table.NewPlugin("cryptoinfo", columns, t.generate)
|
||||
@@ -49,7 +48,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
// We take globs in via the sql %, but glob needs *. So convert.
|
||||
filePaths, err := filepath.Glob(strings.ReplaceAll(requestedPath, `%`, `*`))
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "bad file glob", "err", err)
|
||||
t.logger.Info().Err(err).Msg("bad file glob")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -65,11 +64,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
|
||||
flatData, err := flattenCryptoInfo(filePath, passphrase, flattenOpts...)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log(
|
||||
"msg", "failed to get data for path",
|
||||
"path", filePath,
|
||||
"err", err,
|
||||
)
|
||||
t.logger.Info().Err(err).Str("path", filePath).Msg("failed to get data for path")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,8 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var cryptsetupPaths = []string{
|
||||
@@ -22,17 +21,17 @@ var cryptsetupPaths = []string{
|
||||
const allowedNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/_"
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
name string
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
table.TextColumn("name"),
|
||||
)
|
||||
|
||||
t := &Table{
|
||||
logger: logger,
|
||||
logger: logger.With().Str("table", "cryptsetup_status").Logger(),
|
||||
name: "cryptsetup_status",
|
||||
}
|
||||
|
||||
@@ -54,20 +53,20 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
for _, name := range requestedNames {
|
||||
output, err := tablehelpers.Exec(ctx, t.logger, 15, cryptsetupPaths, []string{"--readonly", "status", name}, false)
|
||||
if err != nil {
|
||||
level.Debug(t.logger).Log("msg", "Error execing for status", "name", name, "err", err)
|
||||
t.logger.Debug().Err(err).Str("name", name).Msg("Error execing for status")
|
||||
continue
|
||||
}
|
||||
|
||||
status, err := parseStatus(output)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "Error parsing status", "name", name, "err", err)
|
||||
t.logger.Info().Err(err).Str("name", name).Msg("Error parsing status")
|
||||
continue
|
||||
}
|
||||
|
||||
for _, dataQuery := range tablehelpers.GetConstraints(queryContext, "query", tablehelpers.WithDefaults("*")) {
|
||||
flatData, err := t.flattenOutput(dataQuery, status)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "flatten failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("flatten failed")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,8 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type ExecTableOpt func(*Table)
|
||||
@@ -35,11 +34,11 @@ func WithBinDirs(binDirs ...string) ExecTableOpt {
|
||||
}
|
||||
}
|
||||
|
||||
func TablePluginExec(logger log.Logger, tableName string, dataSourceType DataSourceType, execArgs []string, opts ...ExecTableOpt) *table.Plugin {
|
||||
func TablePluginExec(logger zerolog.Logger, tableName string, dataSourceType DataSourceType, execArgs []string, opts ...ExecTableOpt) *table.Plugin {
|
||||
columns := Columns()
|
||||
|
||||
t := &Table{
|
||||
logger: level.NewFilter(logger, level.AllowInfo()),
|
||||
logger: logger.With().Str("table", tableName).Logger(),
|
||||
tableName: tableName,
|
||||
execArgs: execArgs,
|
||||
keyValueSeparator: ":",
|
||||
@@ -77,7 +76,7 @@ func (t *Table) generateExec(ctx context.Context, queryContext table.QueryContex
|
||||
|
||||
// If the exec failed for some reason, it's probably better to return no results, and log the,
|
||||
// error. Returning an error here will cause a table failure, and thus break joins
|
||||
level.Info(t.logger).Log("msg", "failed to exec", "err", err)
|
||||
t.logger.Info().Err(err).Msg("failed to exec")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ func (t *Table) generateExec(ctx context.Context, queryContext table.QueryContex
|
||||
|
||||
flattened, err := t.flattenBytesFunc(execBytes, flattenOpts...)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "failure flattening output", "err", err)
|
||||
t.logger.Info().Err(err).Msg("failure flattening output")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -121,7 +120,7 @@ func (t *Table) exec(ctx context.Context) ([]byte, error) {
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
level.Debug(t.logger).Log("msg", "calling %s", "args", cmd.String())
|
||||
t.logger.Debug().Str("args", strings.Join(t.execArgs[1:], " ")).Msgf("calling %s", cmd.String())
|
||||
|
||||
if err := cmd.Run(); os.IsNotExist(err) {
|
||||
// try the next binary
|
||||
|
||||
@@ -9,10 +9,9 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type DataSourceType int
|
||||
@@ -28,7 +27,7 @@ const (
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
tableName string
|
||||
|
||||
flattenFileFunc func(string, ...dataflatten.FlattenOpts) ([]dataflatten.Row, error)
|
||||
@@ -41,7 +40,7 @@ type Table struct {
|
||||
}
|
||||
|
||||
// AllTablePlugins is a helper to return all the expected flattening tables.
|
||||
func AllTablePlugins(logger log.Logger) []osquery.OsqueryPlugin {
|
||||
func AllTablePlugins(logger zerolog.Logger) []osquery.OsqueryPlugin {
|
||||
return []osquery.OsqueryPlugin{
|
||||
TablePlugin(logger, JsonType),
|
||||
TablePlugin(logger, XmlType),
|
||||
@@ -51,7 +50,7 @@ func AllTablePlugins(logger log.Logger) []osquery.OsqueryPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger, dataSourceType DataSourceType) osquery.OsqueryPlugin {
|
||||
func TablePlugin(logger zerolog.Logger, dataSourceType DataSourceType) osquery.OsqueryPlugin {
|
||||
columns := Columns(table.TextColumn("path"))
|
||||
|
||||
t := &Table{
|
||||
@@ -101,11 +100,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
for _, dataQuery := range tablehelpers.GetConstraints(queryContext, "query", tablehelpers.WithDefaults("*")) {
|
||||
subresults, err := t.generatePath(filePath, dataQuery)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log(
|
||||
"msg", "failed to get data for path",
|
||||
"path", filePath,
|
||||
"err", err,
|
||||
)
|
||||
t.logger.Info().Err(err).Str("path", filePath).Msg("failed to get data for path")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -125,7 +120,7 @@ func (t *Table) generatePath(filePath string, dataQuery string) ([]map[string]st
|
||||
|
||||
data, err := t.flattenFileFunc(filePath, flattenOpts...)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "failure parsing file", "file", filePath)
|
||||
t.logger.Info().Err(err).Str("file", filePath).Msg("failure parsing file")
|
||||
return nil, fmt.Errorf("parsing data: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
func TestDataFlattenTablePlist_Animals(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
logger := zerolog.Nop()
|
||||
|
||||
// Test plist parsing both the json and xml forms
|
||||
testTables := map[string]Table{
|
||||
@@ -85,7 +85,7 @@ func TestDataFlattenTablePlist_Animals(t *testing.T) {
|
||||
func TestDataFlattenTables(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := log.NewNopLogger()
|
||||
logger := zerolog.Nop()
|
||||
|
||||
tests := []struct {
|
||||
testTables map[string]Table
|
||||
|
||||
@@ -50,9 +50,6 @@ type PluginOpts struct {
|
||||
Socket string
|
||||
}
|
||||
|
||||
// Logger for osquery tables
|
||||
var osqueryLogger *Logger
|
||||
|
||||
// WithExtension registers the given Extension on the Runner.
|
||||
func WithExtension(t Extension) Opt {
|
||||
return func(r *Runner) {
|
||||
@@ -73,8 +70,6 @@ func NewRunner(socket string, opts ...Opt) *Runner {
|
||||
func (r *Runner) Execute() error {
|
||||
log.Debug().Msg("start osquery extension")
|
||||
|
||||
osqueryLogger = NewOsqueryLogger()
|
||||
|
||||
if err := waitExtensionSocket(r.socket, 1*time.Minute); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -146,14 +141,17 @@ func OrbitDefaultTables() []osquery.OsqueryPlugin {
|
||||
table.NewPlugin("sntp_request", sntp_request.Columns(), sntp_request.GenerateFunc),
|
||||
fleetd_logs.TablePlugin(),
|
||||
|
||||
firefox_preferences.TablePlugin(osqueryLogger),
|
||||
cryptoinfotable.TablePlugin(osqueryLogger),
|
||||
// Note: the logger passed here and to all other tables is the global logger from zerolog.
|
||||
// This logger has already been configured with some required settings in
|
||||
// orbit/cmd/orbit/orbit.go.
|
||||
firefox_preferences.TablePlugin(log.Logger),
|
||||
cryptoinfotable.TablePlugin(log.Logger),
|
||||
|
||||
// Additional data format tables
|
||||
dataflattentable.TablePlugin(osqueryLogger, dataflattentable.JsonType), // table name is "parse_json"
|
||||
dataflattentable.TablePlugin(osqueryLogger, dataflattentable.JsonlType), // table name is "parse_jsonl"
|
||||
dataflattentable.TablePlugin(osqueryLogger, dataflattentable.XmlType), // table name is "parse_xml"
|
||||
dataflattentable.TablePlugin(osqueryLogger, dataflattentable.IniType), // table name is "parse_ini"
|
||||
dataflattentable.TablePlugin(log.Logger, dataflattentable.JsonType), // table name is "parse_json"
|
||||
dataflattentable.TablePlugin(log.Logger, dataflattentable.JsonlType), // table name is "parse_jsonl"
|
||||
dataflattentable.TablePlugin(log.Logger, dataflattentable.XmlType), // table name is "parse_xml"
|
||||
dataflattentable.TablePlugin(log.Logger, dataflattentable.IniType), // table name is "parse_ini"
|
||||
|
||||
}
|
||||
return plugins
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/sudo_info"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tcc_access"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/user_login_settings"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/macadmins/osquery-extension/tables/filevaultusers"
|
||||
"github.com/macadmins/osquery-extension/tables/macos_profiles"
|
||||
@@ -83,14 +84,14 @@ func PlatformTables(opts PluginOpts) ([]osquery.OsqueryPlugin, error) {
|
||||
},
|
||||
),
|
||||
|
||||
filevault_status.TablePlugin(osqueryLogger), // table name is "filevault_status"
|
||||
ioreg.TablePlugin(osqueryLogger), // table name is "ioreg"
|
||||
filevault_status.TablePlugin(log.Logger), // table name is "filevault_status"
|
||||
ioreg.TablePlugin(log.Logger), // table name is "ioreg"
|
||||
|
||||
// firmwarepasswd table. Only returns valid data on a Mac with an Intel processor. Background: https://support.apple.com/en-us/HT204455
|
||||
firmwarepasswd.TablePlugin(osqueryLogger), // table name is "firmwarepasswd"
|
||||
firmwarepasswd.TablePlugin(log.Logger), // table name is "firmwarepasswd"
|
||||
|
||||
// Table for parsing Apple Property List files, which are typically stored in ~/Library/Preferences/
|
||||
dataflattentable.TablePlugin(osqueryLogger, dataflattentable.PlistType), // table name is "parse_plist"
|
||||
dataflattentable.TablePlugin(log.Logger, dataflattentable.PlistType), // table name is "parse_plist"
|
||||
}
|
||||
|
||||
// append platform specific tables
|
||||
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/crowdstrike/falcon_kernel_check"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/crowdstrike/falconctl"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/cryptsetup"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/osquery/osquery-go"
|
||||
)
|
||||
|
||||
func PlatformTables(_ PluginOpts) ([]osquery.OsqueryPlugin, error) {
|
||||
return []osquery.OsqueryPlugin{
|
||||
cryptsetup.TablePlugin(osqueryLogger), // table name is "cryptsetup_status"
|
||||
falconctl.NewFalconctlOptionTable(osqueryLogger), // table name is "falconctl_option"
|
||||
falcon_kernel_check.TablePlugin(osqueryLogger), // table name is "falcon_kernel_check"
|
||||
cryptsetup.TablePlugin(log.Logger), // table name is "cryptsetup_status"
|
||||
falconctl.NewFalconctlOptionTable(log.Logger), // table name is "falconctl_option"
|
||||
falcon_kernel_check.TablePlugin(log.Logger), // table name is "falcon_kernel_check"
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package table
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Logger is a wrapper around zerolog, which we use for tables
|
||||
// using the go-kit logger
|
||||
type Logger struct {
|
||||
zerolog.Logger
|
||||
}
|
||||
|
||||
// Log logs a message, implementing log.Logger interface
|
||||
func (l *Logger) Log(keyValuePairs ...interface{}) error {
|
||||
log.Logger.Info().Msg(fmt.Sprint(keyValuePairs...))
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewOsqueryLogger returns the Logger struct.
|
||||
func NewOsqueryLogger() *Logger {
|
||||
// Return a Logger struct with our global logger, and use the existing global config for the log level.
|
||||
return &Logger{log.Logger}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
cisaudit "github.com/fleetdm/fleet/v4/orbit/pkg/table/cis_audit"
|
||||
mdmbridge "github.com/fleetdm/fleet/v4/orbit/pkg/table/mdm"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/windowsupdatetable"
|
||||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
|
||||
"github.com/osquery/osquery-go"
|
||||
@@ -19,7 +20,7 @@ func PlatformTables(_ PluginOpts) ([]osquery.OsqueryPlugin, error) {
|
||||
// Fleet tables
|
||||
table.NewPlugin("cis_audit", cisaudit.Columns(), cisaudit.Generate),
|
||||
|
||||
windowsupdatetable.TablePlugin(windowsupdatetable.UpdatesTable, osqueryLogger), // table name is "windows_updates"
|
||||
windowsupdatetable.TablePlugin(windowsupdatetable.UpdatesTable, log.Logger), // table name is "windows_updates"
|
||||
}
|
||||
|
||||
windowsServer, err := IsWindowsServer()
|
||||
|
||||
@@ -14,24 +14,23 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const fdesetupPath = "/usr/bin/fdesetup"
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := []table.ColumnDefinition{
|
||||
table.TextColumn("status"),
|
||||
}
|
||||
|
||||
t := &Table{
|
||||
logger: logger,
|
||||
logger: logger.With().Str("table", "filevault_status").Logger(),
|
||||
}
|
||||
|
||||
return table.NewPlugin("filevault_status", columns, t.generate)
|
||||
@@ -40,7 +39,7 @@ func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
|
||||
output, err := tablehelpers.Exec(ctx, t.logger, 10, []string{fdesetupPath}, []string{"status"}, false)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "fdesetup failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("fdesetup failed")
|
||||
|
||||
// Don't error out if the binary isn't found
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
|
||||
@@ -4,7 +4,6 @@ package firefox_preferences
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -12,14 +11,13 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
name string
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
const tableName = "firefox_preferences"
|
||||
@@ -36,14 +34,14 @@ const tableName = "firefox_preferences"
|
||||
// https://github.com/hansmi/go-mozpref
|
||||
var re = regexp.MustCompile(`^user_pref\("([^,]+)",\s*"?(.*?)"?\);$`)
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
table.TextColumn("path"),
|
||||
)
|
||||
|
||||
t := &Table{
|
||||
name: tableName,
|
||||
logger: logger,
|
||||
logger: logger.With().Str("table", tableName).Logger(),
|
||||
}
|
||||
|
||||
return table.NewPlugin(t.name, columns, t.generate)
|
||||
@@ -55,10 +53,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
filePaths := tablehelpers.GetConstraints(queryContext, "path")
|
||||
|
||||
if len(filePaths) == 0 {
|
||||
level.Info(t.logger).Log(
|
||||
"msg", fmt.Sprintf("no path provided to %s", tableName),
|
||||
"table", tableName,
|
||||
)
|
||||
t.logger.Info().Msgf("no path provided to %s", tableName)
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -70,12 +65,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log(
|
||||
"msg", "failed to open file",
|
||||
"table", tableName,
|
||||
"path", filePath,
|
||||
"err", err,
|
||||
)
|
||||
t.logger.Info().Err(err).Str("path", filePath).Msg("failed to open file")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -104,12 +94,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
|
||||
flatData, err := dataflatten.Flatten(rawKeyVals, flattenOpts...)
|
||||
if err != nil {
|
||||
level.Debug(t.logger).Log(
|
||||
"msg", "failed to flatten data for path",
|
||||
"table", tableName,
|
||||
"path", filePath,
|
||||
"err", err,
|
||||
)
|
||||
t.logger.Debug().Err(err).Str("path", filePath).Msg("failed to flatten data for path")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -49,7 +49,7 @@ func Test_generate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
table := Table{logger: log.NewNopLogger()}
|
||||
table := Table{logger: zerolog.Nop()}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
@@ -14,17 +14,16 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
parser *OutputParser
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := []table.ColumnDefinition{
|
||||
table.IntegerColumn("option_roms_allowed"),
|
||||
table.IntegerColumn("password_enabled"),
|
||||
@@ -36,7 +35,7 @@ func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
return table.NewPlugin("firmwarepasswd", columns, t.generate)
|
||||
}
|
||||
|
||||
func New(logger log.Logger) *Table {
|
||||
func New(logger zerolog.Logger) *Table {
|
||||
parser := NewParser(logger,
|
||||
[]Matcher{
|
||||
{
|
||||
@@ -57,7 +56,7 @@ func New(logger log.Logger) *Table {
|
||||
})
|
||||
|
||||
return &Table{
|
||||
logger: level.NewFilter(logger, level.AllowInfo()),
|
||||
logger: logger.With().Str("table", "firmwarepasswd").Logger(),
|
||||
parser: parser,
|
||||
}
|
||||
}
|
||||
@@ -68,11 +67,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
for _, mode := range []string{"-check", "-mode"} {
|
||||
output := new(bytes.Buffer)
|
||||
if err := t.runFirmwarepasswd(ctx, mode, output); err != nil {
|
||||
level.Info(t.logger).Log(
|
||||
"msg", "Error running firmware password",
|
||||
"command", mode,
|
||||
"err", err,
|
||||
)
|
||||
t.logger.Info().Err(err).Str("command", mode).Msg("Error running firmware password")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -110,12 +105,12 @@ func (t *Table) runFirmwarepasswd(ctx context.Context, subcommand string, output
|
||||
cmd.Stdout = output
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
level.Debug(t.logger).Log(
|
||||
"msg", "Error running firmwarepasswd",
|
||||
"stderr", strings.TrimSpace(stderr.String()),
|
||||
"stdout", strings.TrimSpace(output.String()),
|
||||
"err", err,
|
||||
)
|
||||
|
||||
t.logger.Debug().
|
||||
Err(err).
|
||||
Str("stderr", strings.TrimSpace(stderr.String())).
|
||||
Str("stdout", strings.TrimSpace(output.String())).
|
||||
Msg("Error running firmwarepasswd")
|
||||
return fmt.Errorf("running firmwarepasswd: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestParser(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
parser := New(log.NewNopLogger()).parser
|
||||
parser := New(zerolog.Nop()).parser
|
||||
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -5,8 +5,7 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type Matcher struct {
|
||||
@@ -17,10 +16,10 @@ type Matcher struct {
|
||||
|
||||
type OutputParser struct {
|
||||
matchers []Matcher
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
func NewParser(logger log.Logger, matchers []Matcher) *OutputParser {
|
||||
func NewParser(logger zerolog.Logger, matchers []Matcher) *OutputParser {
|
||||
p := &OutputParser{
|
||||
matchers: matchers,
|
||||
logger: logger,
|
||||
@@ -46,21 +45,13 @@ func (p *OutputParser) Parse(input *bytes.Buffer) []map[string]string {
|
||||
if m.Match(line) {
|
||||
key, err := m.KeyFunc(line)
|
||||
if err != nil {
|
||||
level.Debug(p.logger).Log(
|
||||
"msg", "key match failed",
|
||||
"line", line,
|
||||
"err", err,
|
||||
)
|
||||
p.logger.Debug().Err(err).Str("line", line).Msg("key match failed")
|
||||
continue
|
||||
}
|
||||
|
||||
val, err := m.ValFunc(line)
|
||||
if err != nil {
|
||||
level.Debug(p.logger).Log(
|
||||
"msg", "value match failed",
|
||||
"line", line,
|
||||
"err", err,
|
||||
)
|
||||
p.logger.Debug().Err(err).Str("line", line).Msg("value match failed")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -70,14 +61,14 @@ func (p *OutputParser) Parse(input *bytes.Buffer) []map[string]string {
|
||||
}
|
||||
|
||||
if len(row) == 0 {
|
||||
level.Debug(p.logger).Log("msg", "No matched keys", "line", line)
|
||||
p.logger.Debug().Str("line", line).Msg("No matched keys")
|
||||
continue
|
||||
}
|
||||
results = append(results, row)
|
||||
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
level.Debug(p.logger).Log("msg", "scanner error", "err", err)
|
||||
p.logger.Debug().Err(err).Msg("scanner error")
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
@@ -17,9 +17,8 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/dataflatten"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
const ioregPath = "/usr/sbin/ioreg"
|
||||
@@ -27,11 +26,11 @@ const ioregPath = "/usr/sbin/ioreg"
|
||||
const allowedCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
tableName string
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
// ioreg input options. These match the ioreg
|
||||
// command line. See the ioreg man page.
|
||||
@@ -44,8 +43,8 @@ func TablePlugin(logger log.Logger) *table.Plugin {
|
||||
)
|
||||
|
||||
t := &Table{
|
||||
logger: logger,
|
||||
tableName: "ioreg",
|
||||
logger: logger.With().Str("table", "ioreg").Logger(),
|
||||
}
|
||||
|
||||
return table.NewPlugin(t.tableName, columns, t.generate)
|
||||
@@ -94,7 +93,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
case "1":
|
||||
ioregArgs = append(ioregArgs, "-r")
|
||||
default:
|
||||
level.Info(t.logger).Log("msg", "r should be blank, 0, or 1")
|
||||
t.logger.Info().Msg("r should be blank, 0, or 1")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -103,13 +102,13 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
|
||||
ioregOutput, err := tablehelpers.Exec(ctx, t.logger, 30, []string{ioregPath}, ioregArgs, false)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "ioreg failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("ioreg failed ctx logger")
|
||||
continue
|
||||
}
|
||||
|
||||
flatData, err := t.flattenOutput(dataQuery, ioregOutput)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "flatten failed", "err", err)
|
||||
t.logger.Info().Err(err).Msg("flatten failed")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// Exec is a wrapper over exec.CommandContext. It does a couple of
|
||||
@@ -23,7 +22,7 @@ import (
|
||||
// 3. It moves the stderr into the return error, if needed.
|
||||
//
|
||||
// This is not suitable for high performance work -- it allocates new buffers each time.
|
||||
func Exec(ctx context.Context, logger log.Logger, timeoutSeconds int, possibleBins []string, args []string, includeStderr bool) ([]byte, error) {
|
||||
func Exec(ctx context.Context, log zerolog.Logger, timeoutSeconds int, possibleBins []string, args []string, includeStderr bool) ([]byte, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, time.Duration(timeoutSeconds)*time.Second)
|
||||
defer cancel()
|
||||
|
||||
@@ -42,10 +41,7 @@ func Exec(ctx context.Context, logger log.Logger, timeoutSeconds int, possibleBi
|
||||
cmd.Stderr = &stderr
|
||||
}
|
||||
|
||||
level.Debug(logger).Log(
|
||||
"msg", "execing",
|
||||
"cmd", cmd.String(),
|
||||
)
|
||||
log.Debug().Str("cmd", cmd.String()).Msg("execing")
|
||||
|
||||
switch err := cmd.Run(); {
|
||||
case err == nil:
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var tests = []struct {
|
||||
tests := []struct {
|
||||
name string
|
||||
timeout int
|
||||
bins []string
|
||||
@@ -53,7 +53,7 @@ func TestExec(t *testing.T) {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
logger := log.NewNopLogger()
|
||||
logger := zerolog.Nop()
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
@@ -71,7 +71,6 @@ func TestExec(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(tt.output), output)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,22 +4,21 @@ package tablehelpers
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
type constraintOptions struct {
|
||||
allowedCharacters string
|
||||
allowedValues []string
|
||||
defaults []string
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
}
|
||||
|
||||
type GetConstraintOpts func(*constraintOptions)
|
||||
|
||||
// WithLogger sets the logger to use
|
||||
func WithLogger(logger log.Logger) GetConstraintOpts {
|
||||
func WithLogger(logger zerolog.Logger) GetConstraintOpts {
|
||||
return func(co *constraintOptions) {
|
||||
co.logger = logger
|
||||
}
|
||||
@@ -50,7 +49,7 @@ func WithAllowedValues(allowed []string) GetConstraintOpts {
|
||||
// a column. It's meant for the common, simple, usecase of iterating over them.
|
||||
func GetConstraints(queryContext table.QueryContext, columnName string, opts ...GetConstraintOpts) []string {
|
||||
co := &constraintOptions{
|
||||
logger: log.NewNopLogger(),
|
||||
logger: zerolog.Nop(),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
@@ -67,11 +66,10 @@ func GetConstraints(queryContext table.QueryContext, columnName string, opts ...
|
||||
for _, c := range q.Constraints {
|
||||
// No point in checking allowed characters, if we have an allowedValues. Just use it.
|
||||
if len(co.allowedValues) == 0 && !co.OnlyAllowedCharacters(c.Expression) {
|
||||
level.Info(co.logger).Log(
|
||||
"msg", "Disallowed character in expression",
|
||||
"column", columnName,
|
||||
"expression", c.Expression,
|
||||
)
|
||||
co.logger.Info().
|
||||
Str("column", columnName).
|
||||
Str("expression", c.Expression).
|
||||
Msg("Disallowed character in expression")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -85,11 +83,10 @@ func GetConstraints(queryContext table.QueryContext, columnName string, opts ...
|
||||
}
|
||||
|
||||
if skip {
|
||||
level.Info(co.logger).Log(
|
||||
"msg", "Disallowed value in expression",
|
||||
"column", columnName,
|
||||
"expression", c.Expression,
|
||||
)
|
||||
co.logger.Info().
|
||||
Str("column", columnName).
|
||||
Str("expression", c.Expression).
|
||||
Msg("Disallowed value in expression")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,8 @@ import (
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/dataflattentable"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/windows/windowsupdate"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/osquery/osquery-go/plugin/table"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/scjalliance/comshim"
|
||||
)
|
||||
|
||||
@@ -29,20 +28,18 @@ const (
|
||||
)
|
||||
|
||||
type Table struct {
|
||||
logger log.Logger
|
||||
logger zerolog.Logger
|
||||
queryFunc queryFuncType
|
||||
name string
|
||||
}
|
||||
|
||||
func TablePlugin(mode tableMode, logger log.Logger) *table.Plugin {
|
||||
func TablePlugin(mode tableMode, logger zerolog.Logger) *table.Plugin {
|
||||
columns := dataflattentable.Columns(
|
||||
table.TextColumn("locale"),
|
||||
table.IntegerColumn("is_default"),
|
||||
)
|
||||
|
||||
t := &Table{
|
||||
logger: logger,
|
||||
}
|
||||
t := &Table{}
|
||||
|
||||
switch mode {
|
||||
case UpdatesTable:
|
||||
@@ -53,6 +50,8 @@ func TablePlugin(mode tableMode, logger log.Logger) *table.Plugin {
|
||||
t.name = "windows_update_history"
|
||||
}
|
||||
|
||||
t.logger = logger.With().Str("table", t.name).Logger()
|
||||
|
||||
return table.NewPlugin(t.name, columns, t.generate)
|
||||
}
|
||||
|
||||
@@ -72,7 +71,7 @@ func (t *Table) generate(ctx context.Context, queryContext table.QueryContext) (
|
||||
for _, locale := range tablehelpers.GetConstraints(queryContext, "locale", tablehelpers.WithDefaults("_default")) {
|
||||
result, err := t.searchLocale(locale, queryContext)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "got error searching", "locale", locale, "err", err)
|
||||
t.logger.Info().Err(err).Str("locale", locale).Msg("got error searching")
|
||||
continue
|
||||
}
|
||||
results = append(results, result...)
|
||||
@@ -101,7 +100,7 @@ func (t *Table) searchLocale(locale string, queryContext table.QueryContext) ([]
|
||||
for _, dataQuery := range tablehelpers.GetConstraints(queryContext, "query", tablehelpers.WithDefaults("*")) {
|
||||
flatData, err := t.flattenOutput(dataQuery, searchResults)
|
||||
if err != nil {
|
||||
level.Info(t.logger).Log("msg", "flatten failed", "err", err)
|
||||
t.logger.Err(err).Msg("flatten failed")
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/orbit/pkg/table/tablehelpers"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -31,14 +31,14 @@ func TestTable(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
table := Table{
|
||||
logger: log.NewNopLogger(),
|
||||
logger: zerolog.Nop(),
|
||||
queryFunc: tt.queryFunc,
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// ci doesn;t return data, but we can, at least, check that the underlying API doesn't error.
|
||||
// ci doesn't return data, but we can, at least, check that the underlying API doesn't error.
|
||||
_, err := table.generate(ctx, tablehelpers.MockQueryContext(nil))
|
||||
require.NoError(t, err, "generate")
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user