diff --git a/changes/add-mariadb-support b/changes/add-mariadb-support new file mode 100644 index 0000000000..58444aea57 --- /dev/null +++ b/changes/add-mariadb-support @@ -0,0 +1 @@ +* Add support for MariaDB 10.5.4 and later. diff --git a/server/fleet/software.go b/server/fleet/software.go index 5f723d78d9..3dca2ea6f2 100644 --- a/server/fleet/software.go +++ b/server/fleet/software.go @@ -1,6 +1,12 @@ package fleet -import "encoding/json" +import ( + "bytes" + "encoding/json" + "fmt" + + "github.com/pkg/errors" +) type SoftwareStore interface { SaveHostSoftware(host *Host) error @@ -40,9 +46,21 @@ func (v *VulnerabilitiesSlice) Scan(src interface{}) error { } switch typed := src.(type) { case []byte: + // MariaDB 10.5.4 compat fixes: first case is that the IF() doesn't seem to work as expected, so it returns + // the following as the null value + if bytes.Equal(typed, []byte(`{"cve": null, "details_link": null}`)) { + return nil + } + // MariaDB 10.5.4 compat fixes: second case JSON_ARRAYAGG is not very nice in this version, so when there's + // only one item in the array, it figures "you only need the one item in this case! here you go!". So we patch + // the object by making it an array + if len(typed) > 0 && typed[0] == '{' { + typed = []byte(fmt.Sprintf("[%s]", string(typed))) + } + err := json.Unmarshal(typed, v) if err != nil { - return err + return errors.Wrapf(err, "src=%s", string(typed)) } } return nil diff --git a/server/fleet/software_test.go b/server/fleet/software_test.go new file mode 100644 index 0000000000..fb5db26873 --- /dev/null +++ b/server/fleet/software_test.go @@ -0,0 +1,35 @@ +package fleet + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVulnerabilitiesScan(t *testing.T) { + v := &VulnerabilitiesSlice{} + var errorTests = []struct { + name string + jsonString string + errStr string + }{ + { + "bad json input", + `{"badjson"`, + `src=[{"badjson"]: invalid character ']' after object key`, + }, + { + "json object instead of slice", + `"something"`, + `src="something": json: cannot unmarshal string into Go value of type fleet.VulnerabilitiesSlice`, + }, + } + + for _, tt := range errorTests { + t.Run(tt.name, func(t *testing.T) { + err := v.Scan([]byte(tt.jsonString)) + require.Error(t, err) + require.Equal(t, tt.errStr, err.Error()) + }) + } +} diff --git a/server/service/integration_test.go b/server/service/integration_test.go index 8a187e65d0..0aa07f7421 100644 --- a/server/service/integration_test.go +++ b/server/service/integration_test.go @@ -419,7 +419,7 @@ func TestTeamSpecs(t *testing.T) { require.NoError(t, err) assert.Len(t, team.Secrets, 0) - assert.Equal(t, &agentOpts, team.AgentOptions) + require.JSONEq(t, string(agentOpts), string(*team.AgentOptions)) // creates a team with default agent options user, err := ds.UserByEmail("admin1@example.com") @@ -439,9 +439,9 @@ func TestTeamSpecs(t *testing.T) { team, err = ds.TeamByName("team2") require.NoError(t, err) - defaultOpts := json.RawMessage("{\"config\": {\"options\": {\"logger_plugin\": \"tls\", \"pack_delimiter\": \"/\", \"logger_tls_period\": 10, \"distributed_plugin\": \"tls\", \"disable_distributed\": false, \"logger_tls_endpoint\": \"/api/v1/osquery/log\", \"distributed_interval\": 10, \"distributed_tls_max_attempts\": 3}, \"decorators\": {\"load\": [\"SELECT uuid AS host_uuid FROM system_info;\", \"SELECT hostname AS hostname FROM system_info;\"]}}, \"overrides\": {}}") + defaultOpts := `{"config": {"options": {"logger_plugin": "tls", "pack_delimiter": "/", "logger_tls_period": 10, "distributed_plugin": "tls", "disable_distributed": false, "logger_tls_endpoint": "/api/v1/osquery/log", "distributed_interval": 10, "distributed_tls_max_attempts": 3}, "decorators": {"load": ["SELECT uuid AS host_uuid FROM system_info;", "SELECT hostname AS hostname FROM system_info;"]}}, "overrides": {}}` assert.Len(t, team.Secrets, 0) - assert.Equal(t, &defaultOpts, team.AgentOptions) + require.JSONEq(t, defaultOpts, string(*team.AgentOptions)) // updates secrets teamSpecs = applyTeamSpecsRequest{Specs: []*fleet.TeamSpec{{Name: "team2", Secrets: []fleet.EnrollSecret{{Secret: "ABC"}}}}}