diff --git a/changes/28443-add-hash-to-software-title-response b/changes/28443-add-hash-to-software-title-response new file mode 100644 index 0000000000..278f87fce5 --- /dev/null +++ b/changes/28443-add-hash-to-software-title-response @@ -0,0 +1 @@ +- Added `hash_sha256` field to the response for the `GET /software/titles` API. diff --git a/server/datastore/mysql/software_titles.go b/server/datastore/mysql/software_titles.go index 27f76e631c..ce285103a9 100644 --- a/server/datastore/mysql/software_titles.go +++ b/server/datastore/mysql/software_titles.go @@ -320,6 +320,7 @@ SELECT si.platform as package_platform, si.url AS package_url, si.install_during_setup as package_install_during_setup, + si.storage_id as package_storage_id, vat.self_service as vpp_app_self_service, vat.adam_id as vpp_app_adam_id, vat.install_during_setup as vpp_install_during_setup, @@ -337,7 +338,7 @@ LEFT JOIN software_titles_host_counts sthc ON sthc.software_title_id = st.id AND WHERE %s -- placeholder for filter based on software installed on hosts + software installers AND (%s) -GROUP BY st.id, package_self_service, package_name, package_version, package_platform, package_url, package_install_during_setup, vpp_app_self_service, vpp_app_adam_id, vpp_app_version, vpp_app_platform, vpp_app_icon_url, vpp_install_during_setup` +GROUP BY st.id, package_self_service, package_name, package_version, package_platform, package_url, package_install_during_setup, package_storage_id, vpp_app_self_service, vpp_app_adam_id, vpp_app_version, vpp_app_platform, vpp_app_icon_url, vpp_install_during_setup` cveJoinType := "LEFT" if opt.VulnerableOnly { diff --git a/server/datastore/mysql/software_titles_test.go b/server/datastore/mysql/software_titles_test.go index e8daff883e..5ca78cdb4e 100644 --- a/server/datastore/mysql/software_titles_test.go +++ b/server/datastore/mysql/software_titles_test.go @@ -1248,6 +1248,7 @@ func testListSoftwareTitlesAllTeams(t *testing.T, ds *Datastore) { TeamID: nil, UserID: user1.ID, ValidatedLabels: &fleet.LabelIdentsWithScope{}, + StorageID: "abc123", }) require.NoError(t, err) @@ -1309,6 +1310,7 @@ func testListSoftwareTitlesAllTeams(t *testing.T, ds *Datastore) { type nameSource struct { name string source string + hash *string } names := make([]nameSource, 0, len(titles)) for _, title := range titles { @@ -1336,12 +1338,13 @@ func testListSoftwareTitlesAllTeams(t *testing.T, ds *Datastore) { assert.Len(t, titles, 3) names = make([]nameSource, 0, len(titles)) for _, title := range titles { - names = append(names, nameSource{name: title.Name, source: title.Source}) + names = append(names, nameSource{name: title.Name, source: title.Source, hash: title.HashSHA256}) } + expectedHash := "abc123" assert.ElementsMatch(t, []nameSource{ {name: "bar", source: "deb_packages"}, {name: "foo", source: "chrome_extensions"}, - {name: "foobar", source: "apps"}, + {name: "foobar", source: "apps", hash: &expectedHash}, }, names) // List software for "team1". Should list Canva for iOS and macOS. diff --git a/server/fleet/software.go b/server/fleet/software.go index 3d6dd517dd..19da31cc15 100644 --- a/server/fleet/software.go +++ b/server/fleet/software.go @@ -240,6 +240,7 @@ type SoftwareTitleListResult struct { // the software installed. It's surfaced in software_titles to match // with existing software entries. BundleIdentifier *string `json:"bundle_identifier,omitempty" db:"bundle_identifier"` + HashSHA256 *string `json:"hash_sha256,omitempty" db:"package_storage_id"` } type SoftwareTitleListOptions struct { diff --git a/server/service/integration_enterprise_test.go b/server/service/integration_enterprise_test.go index 37c8b88ee0..18cd440d53 100644 --- a/server/service/integration_enterprise_test.go +++ b/server/service/integration_enterprise_test.go @@ -9063,6 +9063,8 @@ func (s *integrationEnterpriseTestSuite) TestAllSoftwareTitles() { require.Len(t, resp.SoftwareTitles, 1) require.NotNil(t, resp.SoftwareTitles[0].SoftwarePackage) + // Test that the software titles endpoint returns a SHA256 hash. + require.Equal(t, *resp.SoftwareTitles[0].HashSHA256, "df06d9ce9e2090d9cb2e8cd1f4d7754a803dc452bf93e3204e3acd3b95508628") // Upload an installer for the same software but different arch to a different team payloadRubyTm2 := &fleet.UploadSoftwareInstallerPayload{