fix panic when reading team features from the database (#7633)

This fixes an unreleased bug I introduced in eeefe2, as the config colum in the teams table is nulleable, it unmarshalls into nil and we can't dereference the variable
This commit is contained in:
Roberto Dip 2022-09-08 10:33:10 -03:00 committed by GitHub
parent 723b76cd2c
commit 2deabc23d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 2 deletions

View file

@ -308,9 +308,13 @@ func (ds *Datastore) TeamFeatures(ctx context.Context, tid uint) (*fleet.Feature
if err := sqlx.GetContext(ctx, ds.reader, &raw, sql, tid); err != nil {
return nil, ctxerr.Wrap(ctx, err, "get team config features")
}
var features fleet.Features
if err := json.Unmarshal(*raw, &features); err != nil {
return nil, ctxerr.Wrap(ctx, err, "unmarshal team config features")
features.ApplyDefaultsForNewInstalls()
if raw != nil {
if err := json.Unmarshal(*raw, &features); err != nil {
return nil, ctxerr.Wrap(ctx, err, "unmarshal team config features")
}
}
return &features, nil
}

View file

@ -10,6 +10,7 @@ import (
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/test"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -30,6 +31,7 @@ func TestTeams(t *testing.T) {
{"TeamAgentOptions", testTeamsAgentOptions},
{"TeamsDeleteRename", testTeamsDeleteRename},
{"DeleteIntegrationsFromTeams", testTeamsDeleteIntegrationsFromTeams},
{"TeamsFeatures", testTeamsFeatures},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
@ -424,3 +426,65 @@ func testTeamsDeleteIntegrationsFromTeams(t *testing.T, ds *Datastore) {
require.NoError(t, err)
assertIntgURLs([]string{urld}, []string{urle, urlf}, []string{urle, urlf})
}
func testTeamsFeatures(t *testing.T, ds *Datastore) {
defaultFeatures := fleet.Features{}
defaultFeatures.ApplyDefaultsForNewInstalls()
ctx := context.Background()
t.Run("NULL config in the database", func(t *testing.T) {
team, err := ds.NewTeam(ctx, &fleet.Team{Name: "team_null_config"})
require.NoError(t, err)
ExecAdhocSQL(t, ds, func(tx sqlx.ExtContext) error {
_, err = tx.ExecContext(
ctx,
"UPDATE teams SET config = NULL WHERE id = ?",
team.ID,
)
return err
})
features, err := ds.TeamFeatures(ctx, team.ID)
require.NoError(t, err)
assert.Equal(t, &defaultFeatures, features)
})
t.Run("NULL config.features in the database", func(t *testing.T) {
team, err := ds.NewTeam(ctx, &fleet.Team{Name: "team_null_config_features"})
require.NoError(t, err)
ExecAdhocSQL(t, ds, func(tx sqlx.ExtContext) error {
_, err = tx.ExecContext(
ctx,
"UPDATE teams SET config = '{}' WHERE id = ?",
team.ID,
)
return err
})
features, err := ds.TeamFeatures(ctx, team.ID)
require.NoError(t, err)
assert.Equal(t, &defaultFeatures, features)
})
t.Run("saves and retrieves configs", func(t *testing.T) {
team, err := ds.NewTeam(ctx, &fleet.Team{
Name: "team1",
Config: fleet.TeamConfig{
Features: fleet.Features{
EnableHostUsers: false,
EnableSoftwareInventory: false,
AdditionalQueries: nil,
},
},
})
require.NoError(t, err)
features, err := ds.TeamFeatures(ctx, team.ID)
require.NoError(t, err)
assert.Equal(t, &fleet.Features{
EnableHostUsers: false,
EnableSoftwareInventory: false,
AdditionalQueries: nil,
}, features)
})
}