mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
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 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## 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. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
ab67979594
commit
9930d34233
2 changed files with 121 additions and 24 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue