From 9930d34233d874dd83989822568fecda0bc07a8a Mon Sep 17 00:00:00 2001 From: Konstantin Sykulev Date: Tue, 8 Jul 2025 10:03:37 -0700 Subject: [PATCH] Make FMA GitOps tests more efficient and less brittle (#30615) Mocking the manifest server to ensure that an app with a no_check hash is always returned (in the event that chrome no longer has this property about it) Mocking the file content in the integration test. There is no reason to really download the real 1password or chrome binaries for this particular case. For: https://github.com/fleetdm/fleet/issues/30325 - [x] Added/updated automated tests ## Summary by CodeRabbit * **Tests** * Enhanced test coverage for software installer payloads with simulated manifest endpoints and SHA256 hash validations. * Added mock servers to verify installer downloads and hash computations for maintained apps, improving batch installer processing tests. --- ee/server/service/software_installers_test.go | 65 ++++++++++++++- server/service/integration_enterprise_test.go | 80 ++++++++++++++----- 2 files changed, 121 insertions(+), 24 deletions(-) diff --git a/ee/server/service/software_installers_test.go b/ee/server/service/software_installers_test.go index 72aabbb898..f11e1c8de9 100644 --- a/ee/server/service/software_installers_test.go +++ b/ee/server/service/software_installers_test.go @@ -2,8 +2,17 @@ package service import ( "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" + "strings" "testing" + ma "github.com/fleetdm/fleet/v4/ee/maintained-apps" "github.com/fleetdm/fleet/v4/server/authz" "github.com/fleetdm/fleet/v4/server/contexts/viewer" "github.com/fleetdm/fleet/v4/server/fleet" @@ -201,6 +210,54 @@ func TestSoftwareInstallerPayloadFromSlug(t *testing.T) { ds := new(mock.Store) svc := newTestService(t, ds) + installerBytes := []byte("1password") + h := sha256.New() + _, err := h.Write(installerBytes) + require.NoError(t, err) + onePasswordSHA := hex.EncodeToString(h.Sum(nil)) + + manifestServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + slug := strings.TrimPrefix(strings.TrimSuffix(r.URL.Path, ".json"), "/") + + var versions []*ma.FMAManifestApp + versions = append(versions, &ma.FMAManifestApp{ + Version: "1", + Queries: ma.FMAQueries{ + Exists: "SELECT 1 FROM osquery_info;", + }, + InstallerURL: fmt.Sprintf("/installer-%s.zip", slug), + InstallScriptRef: "installscript", + UninstallScriptRef: "uninstallscript", + DefaultCategories: []string{"Productivity"}, + }) + + manifest := ma.FMAManifestFile{ + Versions: versions, + Refs: map[string]string{ + "installscript": "echo 'installing'", + "uninstallscript": "echo 'uninstalling'", + }, + } + + switch slug { + case "": + w.WriteHeader(http.StatusNotFound) + return + + case "1password/darwin": + manifest.Versions[0].SHA256 = onePasswordSHA + + case "google-chrome/darwin": + manifest.Versions[0].SHA256 = "no_check" + } + + err := json.NewEncoder(w).Encode(manifest) + require.NoError(t, err) + })) + t.Cleanup(manifestServer.Close) + os.Setenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL", manifestServer.URL) + defer os.Unsetenv("FLEET_DEV_MAINTAINED_APPS_BASE_URL") + ds.GetMaintainedAppBySlugFunc = func(ctx context.Context, slug string, teamID *uint) (*fleet.MaintainedApp, error) { return &fleet.MaintainedApp{ ID: 1, @@ -211,10 +268,10 @@ func TestSoftwareInstallerPayloadFromSlug(t *testing.T) { }, nil } payload := fleet.SoftwareInstallerPayload{Slug: ptr.String("1password/darwin")} - err := svc.softwareInstallerPayloadFromSlug(context.Background(), &payload, nil) + err = svc.softwareInstallerPayloadFromSlug(context.Background(), &payload, nil) require.NoError(t, err) - assert.Contains(t, payload.URL, "1password") - assert.NotEmpty(t, payload.SHA256) + assert.NotEmpty(t, payload.URL) + assert.Equal(t, onePasswordSHA, payload.SHA256) assert.NotEmpty(t, payload.InstallScript) assert.NotEmpty(t, payload.UninstallScript) assert.True(t, payload.FleetMaintained) @@ -232,7 +289,7 @@ func TestSoftwareInstallerPayloadFromSlug(t *testing.T) { payload = fleet.SoftwareInstallerPayload{Slug: ptr.String("google-chrome/darwin")} err = svc.softwareInstallerPayloadFromSlug(context.Background(), &payload, nil) require.NoError(t, err) - assert.Contains(t, payload.URL, "google.com") + assert.NotEmpty(t, payload.URL) assert.Empty(t, payload.SHA256) assert.NotEmpty(t, payload.InstallScript) assert.NotEmpty(t, payload.UninstallScript) diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go index 1f8851d2b6..32a4b10173 100644 --- a/server/service/integration_enterprise_test.go +++ b/server/service/integration_enterprise_test.go @@ -11828,6 +11828,22 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { ////////////////////////// // Do a request with a fleet maintained app ////////////////////////// + oldTransport := http.DefaultTransport + onePassMockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + if _, err := w.Write([]byte("mocked content")); err != nil { + // Handle the error, e.g., log it or fail the test + t.Fatalf("failed to write response: %v", err) + } + })) + defer onePassMockServer.Close() + mockTransport := &mockRoundTripper{ + mockServer: onePassMockServer.URL, + origBaseURL: "https://downloads.1password.com", + next: http.DefaultTransport, + } + http.DefaultTransport = mockTransport + // https://downloads.1password.com/mac/1Password-8.10.82-aarch64.zip maintained1, err := s.ds.UpsertMaintainedApp(ctx, &fleet.MaintainedApp{ Name: "1Password", Slug: "1password/darwin", @@ -11835,13 +11851,6 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { UniqueIdentifier: "com.1password.1password", }) require.NoError(t, err) - maintained2, err := s.ds.UpsertMaintainedApp(ctx, &fleet.MaintainedApp{ - Name: "Google Chrome", - Slug: "google-chrome/darwin", - Platform: "darwin", - UniqueIdentifier: "com.google.Chrome", - }) - require.NoError(t, err) // basic fleet maintained app softwareToInstall = []*fleet.SoftwareInstallerPayload{ @@ -11854,19 +11863,6 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { require.NotNil(t, packages[0].URL) require.Nil(t, packages[0].TeamID) - // maintained app with no_check for sha - softwareToInstall = []*fleet.SoftwareInstallerPayload{ - {Slug: &maintained2.Slug}, - } - s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse) - packages = waitBatchSetSoftwareInstallersCompleted(t, s, "", batchResponse.RequestUUID) - require.Len(t, packages, 1) - require.NotNil(t, packages[0].TitleID) - require.NotNil(t, packages[0].URL) - require.NotNil(t, packages[0].HashSHA256) - require.NotEqual(t, "no_check", packages[0].HashSHA256) - require.Nil(t, packages[0].TeamID) - // with a team s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse, "team_name", tm.Name) packages = waitBatchSetSoftwareInstallersCompleted(t, s, tm.Name, batchResponse.RequestUUID) @@ -11892,6 +11888,50 @@ func (s *integrationEnterpriseTestSuite) TestBatchSetSoftwareInstallers() { require.Len(t, meta.LabelsIncludeAny, 1) require.Equal(t, lblA.ID, meta.LabelsIncludeAny[0].LabelID) require.Equal(t, lblA.Name, meta.LabelsIncludeAny[0].LabelName) + + // maintained app with no_check for sha + // https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg + maintained2, err := s.ds.UpsertMaintainedApp(ctx, &fleet.MaintainedApp{ + Name: "Google Chrome", + Slug: "google-chrome/darwin", + Platform: "darwin", + UniqueIdentifier: "com.google.Chrome", + }) + require.NoError(t, err) + + chromeBytes := []byte("chrome installer content") + h := sha256.New() + _, err = h.Write(chromeBytes) + require.NoError(t, err) + chromeSHA := hex.EncodeToString(h.Sum(nil)) + chromeMockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + if _, err := w.Write(chromeBytes); err != nil { + // Handle the error, e.g., log it or fail the test + t.Fatalf("failed to write response: %v", err) + } + })) + defer chromeMockServer.Close() + mockTransport = &mockRoundTripper{ + mockServer: chromeMockServer.URL, + origBaseURL: "https://dl.google.com", + next: http.DefaultTransport, + } + http.DefaultTransport = mockTransport + + softwareToInstall = []*fleet.SoftwareInstallerPayload{ + {Slug: &maintained2.Slug}, + } + s.DoJSON("POST", "/api/latest/fleet/software/batch", batchSetSoftwareInstallersRequest{Software: softwareToInstall}, http.StatusAccepted, &batchResponse) + packages = waitBatchSetSoftwareInstallersCompleted(t, s, "", batchResponse.RequestUUID) + require.Len(t, packages, 1) + require.NotNil(t, packages[0].TitleID) + require.NotNil(t, packages[0].URL) + // Given that the manifest returns no_check for chrome, the SHA should be taken of the downloaded file. + require.Equal(t, chromeSHA, packages[0].HashSHA256) + require.Nil(t, packages[0].TeamID) + + http.DefaultTransport = oldTransport } func waitBatchSetSoftwareInstallersCompleted(t *testing.T, s *integrationEnterpriseTestSuite, teamName string, requestUUID string) []fleet.SoftwarePackageResponse {