-
Notifications
You must be signed in to change notification settings - Fork 478
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Clear bootstrap package and enrollment profile with GitOps (#26095)
For #25648 Fixed issue where `fleetctl gitops` was NOT deleting macOS setup experience bootstrap package and enrollment profile. GitOps should clear all settings that are not explicitly set in YAML config files. # Checklist for submitter - [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/Committing-Changes.md#changes-files) for more information. - [x] Added/updated automated tests - [x] A detailed QA plan exists on the associated ticket (if it isn't there, work with the product group's QA engineer to add it) - [x] Manual QA for all new/changed functionality
- Loading branch information
Showing
9 changed files
with
361 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Fixed issue where `fleetctl gitops` was NOT deleting macOS setup experience bootstrap package and enrollment profile. GitOps should clear all settings that are not explicitly set in YAML config files. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import ( | |
"testing" | ||
|
||
"github.com/fleetdm/fleet/v4/server/config" | ||
"github.com/fleetdm/fleet/v4/server/datastore/mysql" | ||
"github.com/fleetdm/fleet/v4/server/datastore/redis/redistest" | ||
"github.com/fleetdm/fleet/v4/server/fleet" | ||
appleMdm "github.com/fleetdm/fleet/v4/server/mdm/apple" | ||
|
@@ -18,6 +19,8 @@ import ( | |
"github.com/fleetdm/fleet/v4/server/service" | ||
"github.com/fleetdm/fleet/v4/server/test" | ||
"github.com/go-git/go-git/v5" | ||
"github.com/google/uuid" | ||
"github.com/jmoiron/sqlx" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"github.com/stretchr/testify/suite" | ||
|
@@ -112,35 +115,12 @@ func (s *enterpriseIntegrationGitopsTestSuite) TestFleetGitops() { | |
t := s.T() | ||
const fleetGitopsRepo = "https://github.com/fleetdm/fleet-gitops" | ||
|
||
// Create GitOps user | ||
user := fleet.User{ | ||
Name: "GitOps User", | ||
Email: "[email protected]", | ||
GlobalRole: ptr.String(fleet.RoleGitOps), | ||
} | ||
require.NoError(t, user.SetPassword(test.GoodPassword, 10, 10)) | ||
_, err := s.ds.NewUser(context.Background(), &user) | ||
require.NoError(t, err) | ||
|
||
// Create a temporary fleetctl config file | ||
fleetctlConfig, err := os.CreateTemp(t.TempDir(), "*.yml") | ||
require.NoError(t, err) | ||
token := s.getTestToken(user.Email, test.GoodPassword) | ||
configStr := fmt.Sprintf( | ||
` | ||
contexts: | ||
default: | ||
address: %s | ||
tls-skip-verify: true | ||
token: %s | ||
`, s.server.URL, token, | ||
) | ||
_, err = fleetctlConfig.WriteString(configStr) | ||
require.NoError(t, err) | ||
user := s.createGitOpsUser(t) | ||
fleetctlConfig := s.createFleetctlConfig(t, user) | ||
|
||
// Clone git repo | ||
repoDir := t.TempDir() | ||
_, err = git.PlainClone( | ||
_, err := git.PlainClone( | ||
repoDir, false, &git.CloneOptions{ | ||
ReferenceName: "main", | ||
SingleBranch: true, | ||
|
@@ -235,3 +215,152 @@ team_settings: | |
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", fileName}) | ||
} | ||
} | ||
|
||
func (s *enterpriseIntegrationGitopsTestSuite) createFleetctlConfig(t *testing.T, user fleet.User) *os.File { | ||
fleetctlConfig, err := os.CreateTemp(t.TempDir(), "*.yml") | ||
require.NoError(t, err) | ||
token := s.getTestToken(user.Email, test.GoodPassword) | ||
configStr := fmt.Sprintf( | ||
` | ||
contexts: | ||
default: | ||
address: %s | ||
tls-skip-verify: true | ||
token: %s | ||
`, s.server.URL, token, | ||
) | ||
_, err = fleetctlConfig.WriteString(configStr) | ||
require.NoError(t, err) | ||
return fleetctlConfig | ||
} | ||
|
||
func (s *enterpriseIntegrationGitopsTestSuite) createGitOpsUser(t *testing.T) fleet.User { | ||
user := fleet.User{ | ||
Name: "GitOps User", | ||
Email: uuid.NewString() + "@example.com", | ||
GlobalRole: ptr.String(fleet.RoleGitOps), | ||
} | ||
require.NoError(t, user.SetPassword(test.GoodPassword, 10, 10)) | ||
_, err := s.ds.NewUser(context.Background(), &user) | ||
require.NoError(t, err) | ||
return user | ||
} | ||
|
||
// TestDeleteMacOSSetup tests the deletion of macOS setup assets by `fleetctl gitops` command. | ||
func (s *enterpriseIntegrationGitopsTestSuite) TestDeleteMacOSSetup() { | ||
t := s.T() | ||
|
||
user := s.createGitOpsUser(t) | ||
fleetctlConfig := s.createFleetctlConfig(t, user) | ||
|
||
globalFile, err := os.CreateTemp(t.TempDir(), "*.yml") | ||
require.NoError(t, err) | ||
_, err = globalFile.WriteString(` | ||
agent_options: | ||
controls: | ||
org_settings: | ||
server_settings: | ||
server_url: $FLEET_URL | ||
org_info: | ||
org_name: Fleet | ||
secrets: | ||
policies: | ||
queries: | ||
`) | ||
require.NoError(t, err) | ||
|
||
teamName := uuid.NewString() | ||
teamFile, err := os.CreateTemp(t.TempDir(), "*.yml") | ||
require.NoError(t, err) | ||
_, err = teamFile.WriteString( | ||
fmt.Sprintf( | ||
` | ||
controls: | ||
software: | ||
queries: | ||
policies: | ||
agent_options: | ||
name: %s | ||
team_settings: | ||
secrets: [{"secret":"enroll_secret"}] | ||
`, teamName, | ||
), | ||
) | ||
require.NoError(t, err) | ||
|
||
// Set the required environment variables | ||
t.Setenv("FLEET_URL", s.server.URL) | ||
|
||
// Apply configs | ||
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name(), "-f", teamFile.Name(), "--dry-run"}) | ||
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name(), "-f", teamFile.Name()}) | ||
|
||
// Add bootstrap packages | ||
require.NoError(t, s.ds.InsertMDMAppleBootstrapPackage(context.Background(), &fleet.MDMAppleBootstrapPackage{ | ||
Name: "bootstrap.pkg", | ||
TeamID: 0, | ||
Bytes: []byte("bootstrap package"), | ||
Token: uuid.NewString(), | ||
Sha256: []byte("sha256"), | ||
}, nil)) | ||
team, err := s.ds.TeamByName(context.Background(), teamName) | ||
require.NoError(t, err) | ||
t.Cleanup(func() { | ||
_ = s.ds.DeleteTeam(context.Background(), team.ID) | ||
}) | ||
require.NoError(t, s.ds.InsertMDMAppleBootstrapPackage(context.Background(), &fleet.MDMAppleBootstrapPackage{ | ||
Name: "bootstrap.pkg", | ||
TeamID: team.ID, | ||
Bytes: []byte("bootstrap package"), | ||
Token: uuid.NewString(), | ||
Sha256: []byte("sha256"), | ||
}, nil)) | ||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { | ||
stmt := "SELECT COUNT(*) FROM mdm_apple_bootstrap_packages WHERE team_id IN (?, ?)" | ||
var result int | ||
require.NoError(t, sqlx.GetContext(context.Background(), q, &result, stmt, 0, team.ID)) | ||
assert.Equal(t, 2, result) | ||
return nil | ||
}) | ||
|
||
// Add enrollment profiles | ||
_, err = s.ds.SetOrUpdateMDMAppleSetupAssistant(context.Background(), &fleet.MDMAppleSetupAssistant{ | ||
TeamID: nil, | ||
Name: "enrollment_profile.json", | ||
Profile: []byte(`{"foo":"bar"}`), | ||
}) | ||
require.NoError(t, err) | ||
_, err = s.ds.SetOrUpdateMDMAppleSetupAssistant(context.Background(), &fleet.MDMAppleSetupAssistant{ | ||
TeamID: &team.ID, | ||
Name: "enrollment_profile.json", | ||
Profile: []byte(`{"foo":"bar"}`), | ||
}) | ||
require.NoError(t, err) | ||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { | ||
stmt := "SELECT COUNT(*) FROM mdm_apple_setup_assistants WHERE global_or_team_id IN (?, ?)" | ||
var result int | ||
require.NoError(t, sqlx.GetContext(context.Background(), q, &result, stmt, 0, team.ID)) | ||
assert.Equal(t, 2, result) | ||
return nil | ||
}) | ||
|
||
// Re-apply configs and expect the macOS setup assets to be cleared | ||
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name(), "-f", teamFile.Name(), "--dry-run"}) | ||
_ = runAppForTest(t, []string{"gitops", "--config", fleetctlConfig.Name(), "-f", globalFile.Name(), "-f", teamFile.Name()}) | ||
|
||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { | ||
stmt := "SELECT COUNT(*) FROM mdm_apple_bootstrap_packages WHERE team_id IN (?, ?)" | ||
var result int | ||
require.NoError(t, sqlx.GetContext(context.Background(), q, &result, stmt, 0, team.ID)) | ||
assert.Equal(t, 0, result) | ||
return nil | ||
}) | ||
mysql.ExecAdhocSQL(t, s.ds, func(q sqlx.ExtContext) error { | ||
stmt := "SELECT COUNT(*) FROM mdm_apple_setup_assistants WHERE global_or_team_id IN (?, ?)" | ||
var result int | ||
require.NoError(t, sqlx.GetContext(context.Background(), q, &result, stmt, 0, team.ID)) | ||
assert.Equal(t, 0, result) | ||
return nil | ||
}) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.