mirror of
https://github.com/fleetdm/fleet
synced 2026-05-06 06:48:54 +00:00
Fixes #32239. This changes tags to return a comma-delimited list on multiple tags, the single tag when there's only one, and "is not set" (similar to other values) when no tags are set. Confirmed that this allows us to run `SELECT * FROM falconctl_options` without issue on various configurations of Crowdstrike Falcon on Linux. # Checklist for submitter If some of the following don't apply, delete the relevant line. - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) ## Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## fleetd/orbit/Fleet Desktop - [x] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [x] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes
186 lines
5.1 KiB
Go
186 lines
5.1 KiB
Go
// based on github.com/kolide/launcher/pkg/osquery/tables
|
|
package falconctl
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestParseOptions(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input []byte
|
|
expected any
|
|
expectedErr bool
|
|
}{
|
|
{
|
|
name: "empty",
|
|
expected: map[string]any{},
|
|
},
|
|
{
|
|
name: "--cid",
|
|
input: []byte(`cid="REDACTED"`),
|
|
expected: map[string]any{"cid": "REDACTED"},
|
|
},
|
|
{
|
|
name: "--aid",
|
|
input: []byte(`aid="REDACTED"`),
|
|
expected: map[string]any{"aid": "REDACTED"},
|
|
},
|
|
{
|
|
name: "--apd",
|
|
input: []byte(`apd is not set,`),
|
|
expected: map[string]any{"apd": "is not set"},
|
|
},
|
|
{
|
|
name: "--aph",
|
|
input: []byte(`aph is not set,`),
|
|
expected: map[string]any{"aph": "is not set"},
|
|
},
|
|
{
|
|
name: "--app",
|
|
input: []byte(`app is not set,`),
|
|
expected: map[string]any{"app": "is not set"},
|
|
},
|
|
{
|
|
name: "--rfm-state",
|
|
input: []byte(`rfm-state=false,`),
|
|
expected: map[string]any{"rfm-state": "false"},
|
|
},
|
|
{
|
|
name: "--rfm-reason",
|
|
input: []byte(`rfm-reason=None, code=0x0,`),
|
|
expected: map[string]any{"rfm-reason": "None", "rfm-reason-code": "0x0"},
|
|
},
|
|
{
|
|
name: "--trace",
|
|
input: []byte(`trace is not set,`),
|
|
expected: map[string]any{"trace": "is not set"},
|
|
},
|
|
{
|
|
name: "--feature",
|
|
input: []byte(`feature= (hex bitmask: 0),`),
|
|
expected: map[string]any{"feature": "(hex bitmask: 0)"},
|
|
},
|
|
{
|
|
name: "--metadata-query",
|
|
input: []byte(`metadata-query=enable (unset default),`),
|
|
expected: map[string]any{"metadata-query": "enable"},
|
|
},
|
|
{
|
|
name: "--version",
|
|
input: []byte(`version = 6.45.14203.0,`),
|
|
expected: map[string]any{"version": "6.45.14203.0"},
|
|
},
|
|
{
|
|
name: "--billing",
|
|
input: []byte(`billing is not set,`),
|
|
expected: map[string]any{"billing": "is not set"},
|
|
},
|
|
{
|
|
name: "--tags",
|
|
input: []byte(`tags=kolide-test-1,kolide-test-2,`),
|
|
expected: map[string]any{"tags": "kolide-test-1,kolide-test-2"},
|
|
},
|
|
{
|
|
name: "--tags with no tags",
|
|
input: []byte(`Sensor grouping tags are not set`),
|
|
expected: map[string]any{"tags": "is not set"},
|
|
},
|
|
{
|
|
name: "--rfm-state --rfm-reason --aph --tags",
|
|
input: []byte("aph is not set, rfm-state=false, rfm-reason=None, code=0x0, tags=kolide-test-1,kolide-test-2."),
|
|
expected: map[string]any{
|
|
"aph": "is not set",
|
|
"rfm-reason": "None",
|
|
"rfm-reason-code": "0x0",
|
|
"rfm-state": "false",
|
|
"tags": "kolide-test-1,kolide-test-2",
|
|
},
|
|
},
|
|
{
|
|
name: "-rfm-state --rfm-reason --aph --tags --version",
|
|
input: []byte("aph is not set, rfm-state=false, rfm-reason=None, code=0x0, version = 6.45.14203.0\ntags=kolide-test-1,kolide-test-2, "),
|
|
expected: map[string]any{
|
|
"aph": "is not set",
|
|
"rfm-reason": "None",
|
|
"rfm-reason-code": "0x0",
|
|
"rfm-state": "false",
|
|
"version": "6.45.14203.0",
|
|
"tags": "kolide-test-1,kolide-test-2",
|
|
},
|
|
},
|
|
|
|
// something with a bunch of things
|
|
{
|
|
name: "normal",
|
|
input: readTestFile(t, path.Join("test-data", "options.txt")),
|
|
expected: map[string]any{
|
|
"aid": "is not set",
|
|
"aph": "is not set",
|
|
"app": "is not set",
|
|
"cid": "ac917ab****************************",
|
|
"feature": "is not set",
|
|
"metadata-query": "enable",
|
|
"rfm-reason": "is not set",
|
|
"rfm-state": "is not set",
|
|
"version": "6.38.13501.0",
|
|
},
|
|
},
|
|
{
|
|
name: "--rfm-state --rfm-reason --aph",
|
|
input: []byte("aph is not set, rfm-state=false, rfm-reason=None, code=0x0.\n"),
|
|
expected: map[string]any{"aph": "is not set", "rfm-reason": "None", "rfm-reason-code": "0x0", "rfm-state": "false"},
|
|
},
|
|
{
|
|
name: "cid not set",
|
|
input: readTestFile(t, path.Join("test-data", "cid-error.txt")),
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
name: "all options",
|
|
input: []byte("cid=\"deadbeefdeadbeefdeadbeefdeadbeef\", aid is not set, apd is not set, aph is not set, app is not set, feature is not set, metadata-query=enable (unset default), version = 7.30.18306.0\ntags=foo,bar, rfm-state is not set, rfm-reason is not set,"),
|
|
expected: map[string]any{
|
|
"cid": "deadbeefdeadbeefdeadbeefdeadbeef",
|
|
"aid": "is not set",
|
|
"apd": "is not set",
|
|
"aph": "is not set",
|
|
"app": "is not set",
|
|
"feature": "is not set",
|
|
"metadata-query": "enable",
|
|
"version": "7.30.18306.0",
|
|
"tags": "foo,bar",
|
|
"rfm-state": "is not set",
|
|
"rfm-reason": "is not set",
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
actual, err := parseOptions(bytes.NewReader(tt.input))
|
|
if tt.expectedErr {
|
|
require.Error(t, err)
|
|
return
|
|
}
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, tt.expected, actual)
|
|
})
|
|
}
|
|
}
|
|
|
|
func readTestFile(t *testing.T, filepath string) []byte {
|
|
b, err := os.ReadFile(filepath)
|
|
require.NoError(t, err)
|
|
return b
|
|
}
|