mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 17:08:53 +00:00
Add tests for declarations
This commit is contained in:
parent
b979eddcfc
commit
7964a81828
4 changed files with 241 additions and 8 deletions
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
fleetmdm "github.com/fleetdm/fleet/v4/server/mdm"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm/nanodep/godep"
|
||||
|
|
@ -3393,8 +3394,6 @@ WHERE h.uuid = ?
|
|||
}
|
||||
|
||||
func (ds *Datastore) batchSetMDMAppleDeclarations(ctx context.Context, tx sqlx.ExtContext, tmID *uint, incomingDeclarations []*fleet.MDMAppleDeclaration) ([]*fleet.MDMAppleDeclaration, error) {
|
||||
// TODO(mna): batch-set should not delete the reserved OS updates DDM.
|
||||
|
||||
const insertStmt = `
|
||||
INSERT INTO mdm_apple_declarations (
|
||||
declaration_uuid,
|
||||
|
|
@ -3471,7 +3470,7 @@ WHERE
|
|||
}
|
||||
|
||||
// figure out if we need to delete any declarations
|
||||
keepIdents := make([]any, 0, len(incomingIdents))
|
||||
keepIdents := make([]string, 0, len(incomingIdents))
|
||||
for _, p := range existingDecls {
|
||||
if newP := incomingDecls[p.Identifier]; newP != nil {
|
||||
keepIdents = append(keepIdents, p.Identifier)
|
||||
|
|
@ -3486,7 +3485,7 @@ WHERE
|
|||
delArgs = []any{declTeamID}
|
||||
} else {
|
||||
// delete the obsolete declarations (all those that are not in keepIdents)
|
||||
stmt, args, err := sqlx.In(fmt.Sprintf(fmtDeleteStmt, andIdentNotInList), declTeamID, keepIdents)
|
||||
stmt, args, err := sqlx.In(fmt.Sprintf(fmtDeleteStmt, andIdentNotInList), declTeamID, append(keepIdents, fleetmdm.ListFleetReservedMacOSDeclarationNames()...))
|
||||
// if err != nil || strings.HasPrefix(ds.testBatchSetMDMAppleProfilesErr, "inselect") { // TODO(JVE): do we need to create similar errors for testing decls?
|
||||
// if err == nil {
|
||||
// err = errors.New(ds.testBatchSetMDMAppleProfilesErr)
|
||||
|
|
|
|||
|
|
@ -1693,6 +1693,12 @@ ON DUPLICATE KEY UPDATE
|
|||
keepNames = append(keepNames, p.Name)
|
||||
}
|
||||
}
|
||||
for n := range mdm.FleetReservedProfileNames() {
|
||||
if _, ok := incomingProfs[n]; !ok {
|
||||
// always keep reserved profiles even if they're not incoming
|
||||
keepNames = append(keepNames, n)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
stmt string
|
||||
|
|
|
|||
|
|
@ -116,10 +116,16 @@ func ListFleetReservedWindowsProfileNames() []string {
|
|||
return []string{FleetWindowsOSUpdatesProfileName}
|
||||
}
|
||||
|
||||
// ListFleetReservedAppleDDMProfileNames returns a list of profile names that
|
||||
// are reserved by Fleet for Apple DDM declarations.
|
||||
func ListFleetReservedAppleDDMProfileNames() []string {
|
||||
// ListFleetReservedMacOSProfileNames returns a list of PayloadDisplayName strings
|
||||
// that are reserved by Fleet for macOS.
|
||||
func ListFleetReservedMacOSProfileNames() []string {
|
||||
return []string{FleetFileVaultProfileName, FleetdConfigProfileName}
|
||||
}
|
||||
|
||||
// ListFleetReservedMacOSDeclarationNames returns a list of declaration names
|
||||
// that are reserved by Fleet for Apple DDM declarations.
|
||||
func ListFleetReservedMacOSDeclarationNames() []string {
|
||||
return []string{FleetMacOSUpdatesProfileName}
|
||||
// TODO(mna): use this to filter-out those reserved profiles from status
|
||||
// summaries/filters.
|
||||
// summaries/filters. Reconcile with the previous func...
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6230,6 +6230,54 @@ func (s *integrationMDMTestSuite) assertConfigProfilesByIdentifier(teamID *uint,
|
|||
return profile
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) assertMacOSConfigProfilesByName(teamID *uint, profileName string, exists bool) {
|
||||
t := s.T()
|
||||
if teamID == nil {
|
||||
teamID = ptr.Uint(0)
|
||||
}
|
||||
var cfgProfs []*fleet.MDMAppleConfigProfile
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
return sqlx.SelectContext(context.Background(), q, &cfgProfs, `SELECT name FROM mdm_apple_configuration_profiles WHERE team_id = ?`, teamID)
|
||||
})
|
||||
|
||||
label := "exist"
|
||||
if !exists {
|
||||
label = "not exist"
|
||||
}
|
||||
require.Condition(t, func() bool {
|
||||
for _, p := range cfgProfs {
|
||||
if p.Name == profileName {
|
||||
return exists // success if we want it to exist, failure if we don't
|
||||
}
|
||||
}
|
||||
return !exists
|
||||
}, "a config profile must %s with name: %s", label, profileName)
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) assertMacOSDeclarationsByName(teamID *uint, declarationName string, exists bool) {
|
||||
t := s.T()
|
||||
if teamID == nil {
|
||||
teamID = ptr.Uint(0)
|
||||
}
|
||||
var cfgProfs []*fleet.MDMAppleConfigProfile
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
return sqlx.SelectContext(context.Background(), q, &cfgProfs, `SELECT name FROM mdm_apple_declarations WHERE team_id = ?`, teamID)
|
||||
})
|
||||
|
||||
label := "exist"
|
||||
if !exists {
|
||||
label = "not exist"
|
||||
}
|
||||
require.Condition(t, func() bool {
|
||||
for _, p := range cfgProfs {
|
||||
if p.Name == declarationName {
|
||||
return exists // success if we want it to exist, failure if we don't
|
||||
}
|
||||
}
|
||||
return !exists
|
||||
}, "a config profile must %s with name: %s", label, declarationName)
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) assertWindowsConfigProfilesByName(teamID *uint, profileName string, exists bool) {
|
||||
t := s.T()
|
||||
if teamID == nil {
|
||||
|
|
@ -7423,6 +7471,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
|||
Description: "desc team1_" + t.Name(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
s.assertMacOSDeclarationsByName(&team.ID, servermdm.FleetMacOSUpdatesProfileName, false)
|
||||
|
||||
// add the host to the team
|
||||
err = s.ds.AddHostsToTeam(context.Background(), &team.ID, []uint{h.ID})
|
||||
|
|
@ -7444,6 +7493,7 @@ func (s *integrationMDMTestSuite) TestOrbitConfigNudgeSettings() {
|
|||
},
|
||||
},
|
||||
}, http.StatusOK, &tmResp)
|
||||
s.assertMacOSDeclarationsByName(&team.ID, servermdm.FleetMacOSUpdatesProfileName, true)
|
||||
|
||||
resp = orbitGetConfigResponse{}
|
||||
s.DoJSON("POST", "/api/fleet/orbit/config", json.RawMessage(fmt.Sprintf(`{"orbit_node_key": %q}`, *h.OrbitNodeKey)), http.StatusOK, &resp)
|
||||
|
|
@ -12219,3 +12269,175 @@ func (s *integrationMDMTestSuite) TestIsServerBitlockerStatus() {
|
|||
require.NotNil(t, hr.Host.MDM.OSSettings.DiskEncryption.Status)
|
||||
require.Equal(t, fleet.DiskEncryptionEnforcing, *hr.Host.MDM.OSSettings.DiskEncryption.Status)
|
||||
}
|
||||
|
||||
func (s *integrationMDMTestSuite) TestMDMBatchSetProfilesKeepsReservedNames() {
|
||||
t := s.T()
|
||||
ctx := context.Background()
|
||||
|
||||
checkMacProfs := func(teamID *uint, names ...string) {
|
||||
var count int
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
var tid uint
|
||||
if teamID != nil {
|
||||
tid = *teamID
|
||||
}
|
||||
return sqlx.GetContext(ctx, q, &count, `SELECT COUNT(*) FROM mdm_apple_configuration_profiles WHERE team_id = ?`, tid)
|
||||
})
|
||||
require.Equal(t, len(names), count)
|
||||
for _, n := range names {
|
||||
s.assertMacOSConfigProfilesByName(teamID, n, true)
|
||||
}
|
||||
}
|
||||
|
||||
checkMacDecls := func(teamID *uint, names ...string) {
|
||||
var count int
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
var tid uint
|
||||
if teamID != nil {
|
||||
tid = *teamID
|
||||
}
|
||||
return sqlx.GetContext(ctx, q, &count, `SELECT COUNT(*) FROM mdm_apple_declarations WHERE team_id = ?`, tid)
|
||||
})
|
||||
require.Equal(t, len(names), count)
|
||||
for _, n := range names {
|
||||
s.assertMacOSDeclarationsByName(teamID, n, true)
|
||||
}
|
||||
}
|
||||
|
||||
checkWinProfs := func(teamID *uint, names ...string) {
|
||||
var count int
|
||||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error {
|
||||
var tid uint
|
||||
if teamID != nil {
|
||||
tid = *teamID
|
||||
}
|
||||
return sqlx.GetContext(ctx, q, &count, `SELECT COUNT(*) FROM mdm_windows_configuration_profiles WHERE team_id = ?`, tid)
|
||||
})
|
||||
for _, n := range names {
|
||||
s.assertWindowsConfigProfilesByName(teamID, n, true)
|
||||
}
|
||||
}
|
||||
|
||||
acResp := appConfigResponse{}
|
||||
s.DoJSON("GET", "/api/latest/fleet/config", nil, http.StatusOK, &acResp)
|
||||
require.True(t, acResp.MDM.EnabledAndConfigured)
|
||||
require.True(t, acResp.MDM.WindowsEnabledAndConfigured)
|
||||
|
||||
// ensures that the fleetd profile is created
|
||||
secrets, err := s.ds.GetEnrollSecrets(ctx, nil)
|
||||
require.NoError(t, err)
|
||||
if len(secrets) == 0 {
|
||||
require.NoError(t, s.ds.ApplyEnrollSecrets(ctx, nil, []*fleet.EnrollSecret{{Secret: t.Name()}}))
|
||||
}
|
||||
require.NoError(t, ReconcileAppleProfiles(ctx, s.ds, s.mdmCommander, s.logger))
|
||||
|
||||
// turn on disk encryption and os updates
|
||||
s.DoJSON("PATCH", "/api/latest/fleet/config", json.RawMessage(`{
|
||||
"mdm": {
|
||||
"enable_disk_encryption": true,
|
||||
"windows_updates": {
|
||||
"deadline_days": 3,
|
||||
"grace_period_days": 1
|
||||
},
|
||||
"macos_updates": {
|
||||
"deadline": "2023-12-31",
|
||||
"minimum_version": "13.3.7"
|
||||
}
|
||||
}
|
||||
}`), http.StatusOK, &acResp)
|
||||
checkMacProfs(nil, servermdm.ListFleetReservedMacOSProfileNames()...)
|
||||
checkMacDecls(nil, servermdm.ListFleetReservedMacOSDeclarationNames()...)
|
||||
checkWinProfs(nil, servermdm.ListFleetReservedWindowsProfileNames()...)
|
||||
|
||||
// batch set only windows profiles doesn't remove the reserved names
|
||||
newWinProfile := syncml.ForTestWithData(map[string]string{"l1": "d1"})
|
||||
var testProfiles []fleet.MDMProfileBatchPayload
|
||||
testProfiles = append(testProfiles, fleet.MDMProfileBatchPayload{
|
||||
Name: "n1",
|
||||
Contents: newWinProfile,
|
||||
})
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testProfiles}, http.StatusNoContent)
|
||||
checkMacProfs(nil, servermdm.ListFleetReservedMacOSProfileNames()...)
|
||||
checkWinProfs(nil, append(servermdm.ListFleetReservedWindowsProfileNames(), "n1")...)
|
||||
|
||||
// batch set windows and mac profiles doesn't remove the reserved names
|
||||
newMacProfile := mcBytesForTest("n2", "i2", uuid.NewString())
|
||||
testProfiles = append(testProfiles, fleet.MDMProfileBatchPayload{
|
||||
Name: "n2",
|
||||
Contents: newMacProfile,
|
||||
})
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testProfiles}, http.StatusNoContent)
|
||||
checkMacProfs(nil, append(servermdm.ListFleetReservedMacOSProfileNames(), "n2")...)
|
||||
checkWinProfs(nil, append(servermdm.ListFleetReservedWindowsProfileNames(), "n1")...)
|
||||
|
||||
// batch set only mac profiles doesn't remove the reserved names
|
||||
testProfiles = []fleet.MDMProfileBatchPayload{{
|
||||
Name: "n2",
|
||||
Contents: newMacProfile,
|
||||
}}
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testProfiles}, http.StatusNoContent)
|
||||
checkMacProfs(nil, append(servermdm.ListFleetReservedMacOSProfileNames(), "n2")...)
|
||||
checkWinProfs(nil, servermdm.ListFleetReservedWindowsProfileNames()...)
|
||||
|
||||
// create a team
|
||||
var tmResp teamResponse
|
||||
s.DoJSON("POST", "/api/v1/fleet/teams", map[string]string{"Name": t.Name()}, http.StatusOK, &tmResp)
|
||||
|
||||
// edit team mdm config to turn on disk encryption and os updates
|
||||
s.DoJSON("PATCH", fmt.Sprintf("/api/latest/fleet/teams/%d", tmResp.Team.ID), modifyTeamRequest{
|
||||
TeamPayload: fleet.TeamPayload{
|
||||
Name: ptr.String(t.Name()),
|
||||
MDM: &fleet.TeamPayloadMDM{
|
||||
EnableDiskEncryption: optjson.SetBool(true),
|
||||
WindowsUpdates: &fleet.WindowsUpdates{
|
||||
DeadlineDays: optjson.SetInt(4),
|
||||
GracePeriodDays: optjson.SetInt(1),
|
||||
},
|
||||
MacOSUpdates: &fleet.MacOSUpdates{
|
||||
Deadline: optjson.SetString("2023-12-31"),
|
||||
MinimumVersion: optjson.SetString("13.3.8"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, http.StatusOK, &teamResponse{})
|
||||
|
||||
s.DoJSON("GET", fmt.Sprintf("/api/v1/fleet/teams/%d", tmResp.Team.ID), nil, http.StatusOK, &tmResp)
|
||||
require.True(t, tmResp.Team.Config.MDM.EnableDiskEncryption)
|
||||
require.Equal(t, 4, tmResp.Team.Config.MDM.WindowsUpdates.DeadlineDays.Value)
|
||||
require.Equal(t, 1, tmResp.Team.Config.MDM.WindowsUpdates.GracePeriodDays.Value)
|
||||
require.Equal(t, "2023-12-31", tmResp.Team.Config.MDM.MacOSUpdates.Deadline.Value)
|
||||
require.Equal(t, "13.3.8", tmResp.Team.Config.MDM.MacOSUpdates.MinimumVersion.Value)
|
||||
|
||||
require.NoError(t, ReconcileAppleProfiles(ctx, s.ds, s.mdmCommander, s.logger))
|
||||
|
||||
checkMacProfs(&tmResp.Team.ID, servermdm.ListFleetReservedMacOSProfileNames()...)
|
||||
checkWinProfs(&tmResp.Team.ID, servermdm.ListFleetReservedWindowsProfileNames()...)
|
||||
|
||||
// batch set only windows profiles doesn't remove the reserved names
|
||||
var testTeamProfiles []fleet.MDMProfileBatchPayload
|
||||
testTeamProfiles = append(testTeamProfiles, fleet.MDMProfileBatchPayload{
|
||||
Name: "n1",
|
||||
Contents: newWinProfile,
|
||||
})
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testTeamProfiles}, http.StatusNoContent, "team_id", strconv.Itoa(int(tmResp.Team.ID)))
|
||||
checkMacProfs(&tmResp.Team.ID, servermdm.ListFleetReservedMacOSProfileNames()...)
|
||||
checkWinProfs(&tmResp.Team.ID, append(servermdm.ListFleetReservedWindowsProfileNames(), "n1")...)
|
||||
|
||||
// batch set windows and mac profiles doesn't remove the reserved names
|
||||
testTeamProfiles = append(testTeamProfiles, fleet.MDMProfileBatchPayload{
|
||||
Name: "n2",
|
||||
Contents: newMacProfile,
|
||||
})
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testTeamProfiles}, http.StatusNoContent, "team_id", strconv.Itoa(int(tmResp.Team.ID)))
|
||||
checkMacProfs(&tmResp.Team.ID, append(servermdm.ListFleetReservedMacOSProfileNames(), "n2")...)
|
||||
checkWinProfs(&tmResp.Team.ID, append(servermdm.ListFleetReservedWindowsProfileNames(), "n1")...)
|
||||
|
||||
// batch set only mac profiles doesn't remove the reserved names
|
||||
testTeamProfiles = []fleet.MDMProfileBatchPayload{{
|
||||
Name: "n2",
|
||||
Contents: newMacProfile,
|
||||
}}
|
||||
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: testTeamProfiles}, http.StatusNoContent, "team_id", strconv.Itoa(int(tmResp.Team.ID)))
|
||||
checkMacProfs(&tmResp.Team.ID, append(servermdm.ListFleetReservedMacOSProfileNames(), "n2")...)
|
||||
checkWinProfs(&tmResp.Team.ID, servermdm.ListFleetReservedWindowsProfileNames()...)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue