mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 08:58:41 +00:00
Merge branch 'main' into feat-labels-scoped-software
This commit is contained in:
commit
eb41e7ce8e
26 changed files with 708 additions and 238 deletions
|
|
@ -9,8 +9,6 @@ We've been using Fleet for a few years and we couldn't be happier. The fact that
|
|||
|
||||
## Challenge
|
||||
|
||||
Scaling organizations face a common challenge: managing every device efficiently across varying teams and locations. Here, we take a deeper look at the impact that Fleet has made at a leading financial technology company.
|
||||
|
||||
The leading financial company looked to simplify how they manage devices and reduce tool overlap without sacrificing control over their infrastructure. The use of multiple proprietary device management tools was creating operational silos, and it required specialized expertise for different legacy systems, leading to inefficiencies.
|
||||
|
||||
## Solution
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<div purpose="attribution-quote">
|
||||
|
||||
“After several fast-paced weeks of planning, testing, and collaboration, our corporate engineering team at Foursquare has officially completed the migration to Fleet Device Management as our new device management platform. This move represents a big step forward for us.”
|
||||
After several fast-paced weeks of planning, testing, and collaboration, our corporate engineering team at Foursquare has officially completed the migration to Fleet Device Management as our new device management platform. This move represents a big step forward for us.
|
||||
|
||||
**— Mike Meyer, Manager, Corporate Engineering at Foursquare**
|
||||
</div>
|
||||
|
|
|
|||
79
articles/global-social-media-platform-switches-to-fleet.md
Normal file
79
articles/global-social-media-platform-switches-to-fleet.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Global social media platform switches to Fleet for workstation telemetry
|
||||
|
||||
<div purpose="attribution-quote">
|
||||
|
||||
Context is king for device data, and Fleet provides a way to surface that information to our other teams and partners.
|
||||
|
||||
**- Systems and Infrastructure Manager**
|
||||
</div>
|
||||
|
||||
## Challenge
|
||||
|
||||
One of the largest social media platforms sought to enhance its telemetry capabilities to maintain strict compliance and security without compromising data accessibility and operational efficiency. Managing thousands of devices across multiple platforms had led to fragmented visibility and reliance on manual data handling processes, which were time-consuming and error-prone. Additionally, the existing solution failed to provide actionable insights without significant customization, hindering proactive operations and complicating compliance with ongoing [ISO27002](https://www.iso.org/standard/75652.html) and [SOC audit](https://en.wikipedia.org/wiki/System_and_Organization_Controls) requirements.
|
||||
|
||||
## Solution
|
||||
|
||||
The social media platform transitioned to Fleet, consolidating under a single, [multi-platform](https://fleetdm.com/orchestration) system that supports macOS, Linux, and Windows. Fleet's compliance features made it easier to meet regulatory standards and protect sensitive data. Leveraging Fleet's real-time reporting and flexible data management capabilities eliminated the need for manual workflows and extensive customizations. Additionally, deploying [osquery](https://osquery.io/) independently from their existing EDR enhanced data accuracy and reliability, providing more accurate measurement against other benchmarks like [CIS](https://www.cisecurity.org/cis-benchmarks), and standardized osquery operations across their entire fleet.
|
||||
|
||||
## Results
|
||||
|
||||
<div purpose="checklist">
|
||||
|
||||
Verifiable compliance
|
||||
|
||||
Cross-team data accessibility
|
||||
|
||||
Real-time insights
|
||||
|
||||
Standardized processes
|
||||
</div>
|
||||
|
||||
By switching to Fleet, they were able to institute more stringent compliance policies, verify security posture, gather real-time insight into ongoing operations, and standardize these processes across their growing fleet of diverse devices and teams.
|
||||
|
||||
|
||||
## Their story
|
||||
|
||||
This social media platform is one of the largest globally, connecting thousands of communities and millions of users. With a vast user base and a significant global presence, effective visibility is essential to maintaining their required performance, security, and compliance standards.
|
||||
|
||||
The decision to switch to Fleet was driven by a few key factors. Strict adherence to compliance standards, balancing proactive and reactive security measures to protect sensitive data, and streamlining device data accessibility. By making data easily accessible and parsable, Fleet eliminated the inefficiencies of manual workflows and addressed communication gaps across teams, enabling better, faster decision-making.
|
||||
|
||||
|
||||
With Fleet, they achieved this through:
|
||||
|
||||
- Eliminating tool overlap
|
||||
|
||||
- Definitive data for compliance and real-time reporting
|
||||
|
||||
- Robust API and webhook support
|
||||
|
||||
- A Unified reporting language
|
||||
|
||||
### Eliminate tool overlap
|
||||
|
||||
Fleet’s centralized platform enabled the combination of device operations across macOS, Windows, and Linux with a [unified reporting language](https://fleetdm.com/docs/deploy/reference-architectures#mysql) that provides flexibility and contextualized data. By adhering to standard data shapes and formats, Fleet makes sure that data is easily interpretable and usable across various teams and applications while serving as the central hub for security data.
|
||||
|
||||
### Definitive data for compliance
|
||||
|
||||
Fleet’s live query engine streams easily accessible and parsable [data](https://fleetdm.com/tables/account_policy_data), eliminating the need for manual exports and data consolidation from multiple tools. With accurate visibility and access across teams, remediations based on information directly from each device lead to fewer infrastructure failures and auditing errors.
|
||||
|
||||
### Robust API and webhook support
|
||||
|
||||
Fleet’s API facilitates real-time [compliance](https://fleetdm.com/queries) auditing and reporting, allowing the team to respond promptly to potential issues by combining data from different tools. The [API](https://fleetdm.com/docs/rest-api/rest-api) and webhook features enable automation and integration with existing systems, eliminating the need for extra middleware and reducing reliance on manual configurations.
|
||||
|
||||
### Unified reporting language
|
||||
|
||||
Fleet's straightforward deployment of the osquery agent across their devices as an independent element ensured data accuracy and reliability while standardizing its operations across macOS, Windows, and Linux. This allowed the social media platform to inspect, collect, fix, install, patch, and program just about anything, every minute of the day, on any computer in their infrastructure, with an unnoticeable performance impact
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
Transitioning to Fleet provided the platform with a strategic solution that addressed its critical needs for compliance, security, data accessibility, and operational efficiency. Fleet's cross-platform support and open-source transparency set it apart from competitors, providing a single source of truth for all devices.
|
||||
|
||||
<call-to-action></call-to-action>
|
||||
|
||||
<meta name="category" value="announcements">
|
||||
<meta name="authorGitHubUsername" value="Drew-P-drawers">
|
||||
<meta name="authorFullName" value="Andrew Baker">
|
||||
<meta name="publishedOn" value="2024-12-16">
|
||||
<meta name="articleTitle" value="Global social media platform migrates to Fleet">
|
||||
<meta name="description" value="Global social media platform migrates to Fleet">
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
# Seamless macOS MDM migration
|
||||
|
||||
> NOTE: Please contact Fleet here https://fleetdm.com/contact or reach out to the Fleet Customer Success team if you are a current Fleet customer for consultation when considering this migration path. We'd love to help!
|
||||
|
||||

|
||||
|
||||
Migrating macOS devices between Mobile Device Management (MDM) solutions is often fraught with challenges, including potential gaps in device management, user disruption, and compliance issues. Traditional MDM migrations typically require end-user interaction and leave devices unmanaged for a period, leading to problems like Wi-Fi disconnections due to certificate profile removal and incomplete migrations. These challenges can force organizations to stay with outdated MDM solutions that no longer meet their needs. But there’s a better way.
|
||||
|
|
|
|||
1
changes/22723-jetbrains-eap-versions
Normal file
1
changes/22723-jetbrains-eap-versions
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Aliased EAP versions of JetBrains IDEs to "last release version plus all fixes" (e.g. 2024.3 EAP -> 2024.2.99) to avoid vulnerability false positives
|
||||
1
changes/23309-mastodon-in-email-templates
Normal file
1
changes/23309-mastodon-in-email-templates
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Added Mastodon icon and URL to server email templates.
|
||||
1
changes/24795-add-helpful-tooltip-setup-experience
Normal file
1
changes/24795-add-helpful-tooltip-setup-experience
Normal file
|
|
@ -0,0 +1 @@
|
|||
- add helpful tooltip for the install software setup experience page
|
||||
|
|
@ -309,7 +309,7 @@ func checkWinVulnerabilities(
|
|||
"found new", len(r))
|
||||
results = append(results, r...)
|
||||
if err != nil {
|
||||
errHandler(ctx, logger, "analyzing hosts for Windows vulnerabilities", err)
|
||||
errHandler(ctx, kitlog.With(logger, "os name", o.Name, "display version", o.DisplayVersion), "analyzing hosts for Windows vulnerabilities", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ If a table is not available for your host, Fleet will generally handle things be
|
|||
|
||||
Fleet Desktop is supported on Ubuntu and Fedora.
|
||||
|
||||
Fedora requires a [gnome extension](https://extensions.gnome.org/extension/615/appindicator-support/) and Google Chrome for Fleet Desktop.
|
||||
Fedora and some flavors of Ubuntu (e.g. Kubuntu) require a [gnome extension](https://extensions.gnome.org/extension/615/appindicator-support/) and Google Chrome for Fleet Desktop.
|
||||
|
||||
Fleet's default (un)install scripts use `apt-get` for Debian-based distributions, and `dnf` for Red Hat-based distributions. To install packages on CentOS versions prior to 8, either add `dnf` or edit install and uninstall scripts to use the `yum` or `rpm` command.
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,10 @@ describe("AddInstallSoftware", () => {
|
|||
);
|
||||
|
||||
expect(
|
||||
screen.getByText(/2 software will be installed during setup/)
|
||||
screen.getByText(
|
||||
(_, element) =>
|
||||
element?.textContent === "2 software will be installed during setup."
|
||||
)
|
||||
).toBeVisible();
|
||||
expect(
|
||||
screen.getByRole("button", { name: "Show selected software" })
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import Button from "components/buttons/Button";
|
|||
import CustomLink from "components/CustomLink";
|
||||
import { ISoftwareTitle } from "interfaces/software";
|
||||
import LinkWithContext from "components/LinkWithContext";
|
||||
import TooltipWrapper from "components/TooltipWrapper";
|
||||
|
||||
const baseClass = "add-install-software";
|
||||
|
||||
|
|
@ -45,9 +46,17 @@ const AddInstallSoftware = ({
|
|||
software.app_store_app?.install_during_setup
|
||||
).length;
|
||||
|
||||
return installDuringSetupCount === 0
|
||||
? "No software added."
|
||||
: `${installDuringSetupCount} software will be installed during setup.`;
|
||||
return installDuringSetupCount === 0 ? (
|
||||
"No software added."
|
||||
) : (
|
||||
<>
|
||||
{installDuringSetupCount} software will be{" "}
|
||||
<TooltipWrapper position="top" tipContent="Software order will vary.">
|
||||
installed during setup
|
||||
</TooltipWrapper>
|
||||
.
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const getButtonText = () => {
|
||||
|
|
|
|||
|
|
@ -132,6 +132,10 @@ resource "aws_ecs_task_definition" "backend" {
|
|||
}
|
||||
]
|
||||
environment = concat([
|
||||
{
|
||||
name = "FLEET_LOGGING_JSON"
|
||||
value = "true"
|
||||
},
|
||||
{
|
||||
name = "FLEET_MYSQL_USERNAME"
|
||||
value = module.aurora_mysql.cluster_master_username
|
||||
|
|
|
|||
|
|
@ -143,6 +143,13 @@
|
|||
src="{{.AssetURL}}/fleet-mark-color-40x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discuss.systems/@Fleet" target="_blank">
|
||||
<img
|
||||
alt="Mastodon logo"
|
||||
style="height: 20px; width: 20px; padding-right: 20px"
|
||||
src="{{.AssetURL}}/mastodon-logo-50x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/fleetctl" target="_blank">
|
||||
<img
|
||||
alt="X logo"
|
||||
|
|
|
|||
|
|
@ -176,6 +176,13 @@
|
|||
src="{{.AssetURL}}/fleet-mark-color-40x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discuss.systems/@Fleet" target="_blank">
|
||||
<img
|
||||
alt="Mastodon logo"
|
||||
style="height: 20px; width: 20px; padding-right: 20px"
|
||||
src="{{.AssetURL}}/mastodon-logo-50x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/fleetctl" target="_blank">
|
||||
<img
|
||||
alt="X logo"
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@
|
|||
src="{{.AssetURL}}/fleet-mark-color-40x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discuss.systems/@Fleet" target="_blank">
|
||||
<img
|
||||
alt="Mastodon logo"
|
||||
style="height: 20px; width: 20px; padding-right: 20px"
|
||||
src="{{.AssetURL}}/mastodon-logo-50x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/fleetctl" target="_blank">
|
||||
<img
|
||||
alt="X logo"
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@
|
|||
src="{{.AssetURL}}/fleet-mark-color-40x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discuss.systems/@Fleet" target="_blank">
|
||||
<img
|
||||
alt="Mastodon logo"
|
||||
style="height: 20px; width: 20px; padding-right: 20px"
|
||||
src="{{.AssetURL}}/mastodon-logo-50x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/fleetctl" target="_blank">
|
||||
<img
|
||||
alt="X logo"
|
||||
|
|
|
|||
|
|
@ -122,6 +122,13 @@
|
|||
src="{{.AssetURL}}/fleet-mark-color-40x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://discuss.systems/@Fleet" target="_blank">
|
||||
<img
|
||||
alt="Mastodon logo"
|
||||
style="height: 20px; width: 20px; padding-right: 20px"
|
||||
src="{{.AssetURL}}/mastodon-logo-50x40@2x.png"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://twitter.com/fleetctl" target="_blank">
|
||||
<img
|
||||
alt="X logo"
|
||||
|
|
|
|||
|
|
@ -1599,15 +1599,9 @@ func directIngestSoftware(ctx context.Context, logger log.Logger, host *fleet.Ho
|
|||
var (
|
||||
macOSMSTeamsVersion = regexp.MustCompile(`(\d).00.(\d)(\d+)`)
|
||||
citrixName = regexp.MustCompile(`Citrix Workspace [0-9]+`)
|
||||
)
|
||||
|
||||
// sanitizeSoftware performs any sanitization required to the ingested software fields.
|
||||
//
|
||||
// Some fields are reported with known incorrect values and we need to fix them before using them.
|
||||
func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
||||
softwareSanitizers := []struct {
|
||||
softwareSanitizers = []struct {
|
||||
checkSoftware func(*fleet.Host, *fleet.Software) bool
|
||||
mutateSoftware func(*fleet.Software)
|
||||
mutateSoftware func(*fleet.Software, log.Logger)
|
||||
}{
|
||||
// "Microsoft Teams" on macOS defines the `bundle_short_version` (CFBundleShortVersionString) in a different
|
||||
// unexpected version format. Thus here we transform the version string to the expected format
|
||||
|
|
@ -1623,7 +1617,7 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
checkSoftware: func(h *fleet.Host, s *fleet.Software) bool {
|
||||
return h.Platform == "darwin" && (s.Name == "Microsoft Teams.app" || s.Name == "Microsoft Teams classic.app")
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software) {
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
if matches := macOSMSTeamsVersion.FindStringSubmatch(s.Version); len(matches) > 0 {
|
||||
s.Version = fmt.Sprintf("%s.%s.00.%s", matches[1], matches[2], matches[3])
|
||||
}
|
||||
|
|
@ -1635,7 +1629,7 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
checkSoftware: func(h *fleet.Host, s *fleet.Software) bool {
|
||||
return h.Platform == "windows" && s.Name == "Cloudflare WARP" && s.Source == "programs"
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software) {
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
// Perform some sanity check on the version before mutating it.
|
||||
parts := strings.Split(s.Version, ".")
|
||||
if len(parts) <= 1 {
|
||||
|
|
@ -1658,7 +1652,7 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
checkSoftware: func(h *fleet.Host, s *fleet.Software) bool {
|
||||
return citrixName.Match([]byte(s.Name)) || s.Name == "Citrix Workspace.app"
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software) {
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
parts := strings.Split(s.Version, ".")
|
||||
if len(parts) <= 1 {
|
||||
level.Debug(logger).Log("msg", "failed to parse software version", "name", s.Name, "version", s.Version)
|
||||
|
|
@ -1694,7 +1688,7 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
checkSoftware: func(h *fleet.Host, s *fleet.Software) bool {
|
||||
return s.Name == "minio" && strings.Contains(s.Version, "RELEASE.")
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software) {
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
s.Version = strings.TrimPrefix(s.Version, "RELEASE.")
|
||||
},
|
||||
},
|
||||
|
|
@ -1705,7 +1699,7 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
|
||||
return s.Name == "minio" && regex.MatchString(s.Version)
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software) {
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
timestamp, err := time.Parse("20060102150405", s.Version)
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "failed to parse software version", "name", s.Name, "version", s.Version, "err", err)
|
||||
|
|
@ -1714,11 +1708,54 @@ func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
|||
s.Version = timestamp.Format("2006-01-02T15-04-05Z")
|
||||
},
|
||||
},
|
||||
}
|
||||
{
|
||||
// JetBrains EAP version numbers aren't what are used in CPEs; this handles the translation for Mac versions.
|
||||
// See #22723 for background. Bundle identifier for EAPs also ends with "-EAP" but checking version makes it
|
||||
// a bit easier to add other platforms later. EAP version numbers are e.g. EAP GO-243.21565.42, and checking
|
||||
// here for the dash ensures that string splitting in the mutator always works without a bounds check.
|
||||
checkSoftware: func(h *fleet.Host, s *fleet.Software) bool {
|
||||
return s.BundleIdentifier != "" && strings.HasPrefix(s.BundleIdentifier, "com.jetbrains.") &&
|
||||
strings.HasPrefix(s.Version, "EAP ") && strings.Contains(s.Version, "-")
|
||||
},
|
||||
mutateSoftware: func(s *fleet.Software, logger log.Logger) {
|
||||
// 243 -> 2024.3
|
||||
eapMajorVersion := strings.Split(strings.Split(s.Version, "-")[1], ".")[0]
|
||||
yearBasedMajorVersion, err := strconv.Atoi("20" + eapMajorVersion[:2])
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "failed to parse JetBrains EAP major version", "version", s.Version, "err", err)
|
||||
return
|
||||
}
|
||||
yearBasedMinorVersion, err := strconv.Atoi(eapMajorVersion[2:])
|
||||
if err != nil {
|
||||
level.Debug(logger).Log("msg", "failed to parse JetBrains EAP minor version", "version", s.Version, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// EAPs are treated as having all fixes from the previous year-based release, but no fixes from the
|
||||
// year-based release they're an EAP of. The exception to this would be CVE-2024-37051, which was fixed
|
||||
// in a second/third EAP depending on product, but at this point all vulnerable EAPs force exit on
|
||||
// startup due to being expired, so that CVE can't be exploited.
|
||||
yearBasedMinorVersion -= 1
|
||||
if yearBasedMinorVersion <= 0 { // wrap e.g. 2024.1 to 2023.4 (not a real version, but has all 2023.3 fixes)
|
||||
yearBasedMajorVersion -= 1
|
||||
yearBasedMinorVersion = 4
|
||||
}
|
||||
|
||||
// pass through minor and patch version for EAP to tell different EAP builds apart
|
||||
eapMinorAndPatchVersion := strings.Join(strings.Split(strings.Split(s.Version, "-")[1], ".")[1:], ".")
|
||||
s.Version = fmt.Sprintf("%d.%d.%s.%s", yearBasedMajorVersion, yearBasedMinorVersion, "99", eapMinorAndPatchVersion)
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// sanitizeSoftware performs any sanitization required to the ingested software fields.
|
||||
//
|
||||
// Some fields are reported with known incorrect values and we need to fix them before using them.
|
||||
func sanitizeSoftware(h *fleet.Host, s *fleet.Software, logger log.Logger) {
|
||||
for _, softwareSanitizer := range softwareSanitizers {
|
||||
if softwareSanitizer.checkSoftware(h, s) {
|
||||
softwareSanitizer.mutateSoftware(s)
|
||||
softwareSanitizer.mutateSoftware(s, logger)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1920,6 +1920,48 @@ func TestSanitizeSoftware(t *testing.T) {
|
|||
Version: "2020-03-10T00-00-00Z",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "JetBrains non-EAP",
|
||||
h: &fleet.Host{},
|
||||
s: &fleet.Software{
|
||||
Name: "GoLand.app",
|
||||
Version: "2024.3.1",
|
||||
BundleIdentifier: "com.jetbrains.goland",
|
||||
},
|
||||
sanitized: &fleet.Software{
|
||||
Name: "GoLand.app",
|
||||
Version: "2024.3.1",
|
||||
BundleIdentifier: "com.jetbrains.goland",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "JetBrains EAP",
|
||||
h: &fleet.Host{},
|
||||
s: &fleet.Software{
|
||||
Name: "GoLand.app",
|
||||
Version: "EAP GO-243.21565.42",
|
||||
BundleIdentifier: "com.jetbrains.goland-EAP",
|
||||
},
|
||||
sanitized: &fleet.Software{
|
||||
Name: "GoLand.app",
|
||||
Version: "2024.2.99.21565.42",
|
||||
BundleIdentifier: "com.jetbrains.goland-EAP",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "JetBrains year-wrapped EAP",
|
||||
h: &fleet.Host{},
|
||||
s: &fleet.Software{
|
||||
Name: "IntelliJ IDEA CE",
|
||||
Version: "EAP IC-241.12345.67",
|
||||
BundleIdentifier: "com.jetbrains.intellij-EAP",
|
||||
},
|
||||
sanitized: &fleet.Software{
|
||||
Name: "IntelliJ IDEA CE",
|
||||
Version: "2023.4.99.12345.67",
|
||||
BundleIdentifier: "com.jetbrains.intellij-EAP",
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
sanitizeSoftware(tc.h, tc.s, log.NewNopLogger())
|
||||
|
|
|
|||
|
|
@ -66,7 +66,53 @@ func (p Products) GetMatchForOS(ctx context.Context, os fleet.OperatingSystem) (
|
|||
}
|
||||
|
||||
func NewProductFromFullName(fullName string) Product {
|
||||
return Product(fullName)
|
||||
// If the full name includes a version, return it as-is.
|
||||
p := Product(fullName)
|
||||
if p.HasDisplayVersion() {
|
||||
return p
|
||||
}
|
||||
|
||||
// Several Windows products listed in MSRC bulletins don't include the OS version number.
|
||||
// We need this to match the product with a host's OS, so we'll add them here.
|
||||
versionString := ""
|
||||
switch {
|
||||
case strings.Contains(fullName, "Windows Server 2022"):
|
||||
versionString = "21H2"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2016"):
|
||||
versionString = "1607"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2019"):
|
||||
versionString = "1809"
|
||||
|
||||
case strings.Contains(fullName, "Windows 8.1"):
|
||||
versionString = "6.3 / NT 6.3"
|
||||
|
||||
case strings.Contains(fullName, "Windows RT 8.1"):
|
||||
versionString = "6.3 / NT 6.3"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2012 R2"):
|
||||
versionString = "6.3 / NT 6.3"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2012"):
|
||||
versionString = "6.2 / NT 6.2"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2008 R2"):
|
||||
versionString = "6.1 / NT 6.1"
|
||||
|
||||
case strings.Contains(fullName, "Windows 7"):
|
||||
versionString = "6.1 / NT 6.1"
|
||||
|
||||
case strings.Contains(fullName, "Windows Server 2008"):
|
||||
versionString = "6.0 / NT 6.0"
|
||||
}
|
||||
|
||||
finalName := fullName
|
||||
if versionString != "" {
|
||||
finalName += (" Version " + versionString)
|
||||
}
|
||||
|
||||
return Product(finalName)
|
||||
}
|
||||
|
||||
func NewProductFromOS(os fleet.OperatingSystem) Product {
|
||||
|
|
|
|||
|
|
@ -67,354 +67,424 @@ func TestMatches(t *testing.T) {
|
|||
|
||||
func TestFullProductName(t *testing.T) {
|
||||
testCases := []struct {
|
||||
fullName string
|
||||
arch string
|
||||
prodName string
|
||||
fullName string
|
||||
arch string
|
||||
prodName string
|
||||
finalName string
|
||||
}{
|
||||
{
|
||||
fullName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1809 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1809 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1809 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2019",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
fullName: "Windows Server 2019",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
finalName: "Windows Server 2019 Version 1809",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2019 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
fullName: "Windows Server 2019 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
finalName: "Windows Server 2019 (Server Core installation) Version 1809",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1909 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1909 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1909 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1909 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1909 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1909 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H1 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H1 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H1 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H1 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H1 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H1 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H1 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H1 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H1 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2022",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2022",
|
||||
fullName: "Windows Server 2022",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2022",
|
||||
finalName: "Windows Server 2022 Version 21H2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2022 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2022",
|
||||
fullName: "Windows Server 2022 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2022",
|
||||
finalName: "Windows Server 2022 (Server Core installation) Version 21H2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 20H2 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 20H2 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 20H2 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 20H2 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 20H2 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 20H2 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 20H2 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 20H2 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 20H2 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server, version 20H2 (Server Core Installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
fullName: "Windows Server, version 20H2 (Server Core Installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
finalName: "Windows Server, version 20H2 (Server Core Installation)",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 11 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 11",
|
||||
fullName: "Windows 11 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 11",
|
||||
finalName: "Windows 11 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 11 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 11",
|
||||
fullName: "Windows 11 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 11",
|
||||
finalName: "Windows 11 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H2 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H2 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H2 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H2 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H2 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H2 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 21H2 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 21H2 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 21H2 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1607 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1607 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1607 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2016",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
fullName: "Windows Server 2016",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
finalName: "Windows Server 2016 Version 1607",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2016 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
fullName: "Windows Server 2016 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
finalName: "Windows Server 2016 (Server Core installation) Version 1607",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 8.1 for 32-bit systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 8.1",
|
||||
fullName: "Windows 8.1 for 32-bit systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 8.1",
|
||||
finalName: "Windows 8.1 for 32-bit systems Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 8.1 for x64-based systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 8.1",
|
||||
fullName: "Windows 8.1 for x64-based systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 8.1",
|
||||
finalName: "Windows 8.1 for x64-based systems Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows RT 8.1",
|
||||
arch: "all",
|
||||
prodName: "Windows RT 8.1",
|
||||
fullName: "Windows RT 8.1",
|
||||
arch: "all",
|
||||
prodName: "Windows RT 8.1",
|
||||
finalName: "Windows RT 8.1 Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
fullName: "Windows Server 2012",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
finalName: "Windows Server 2012 Version 6.2 / NT 6.2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
fullName: "Windows Server 2012 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
finalName: "Windows Server 2012 (Server Core installation) Version 6.2 / NT 6.2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 R2",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
fullName: "Windows Server 2012 R2",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
finalName: "Windows Server 2012 R2 Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 R2 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
fullName: "Windows Server 2012 R2 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
finalName: "Windows Server 2012 R2 (Server Core installation) Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 7 for 32-bit Systems Service Pack 1",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 7",
|
||||
fullName: "Windows 7 for 32-bit Systems Service Pack 1",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 7",
|
||||
finalName: "Windows 7 for 32-bit Systems Service Pack 1 Version 6.1 / NT 6.1",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 7 for x64-based Systems Service Pack 1",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 7",
|
||||
fullName: "Windows 7 for x64-based Systems Service Pack 1",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 7",
|
||||
finalName: "Windows 7 for x64-based Systems Service Pack 1 Version 6.1 / NT 6.1",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for 32-bit Systems Service Pack 2 Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation) Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for x64-based Systems Service Pack 2",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for x64-based Systems Service Pack 2",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for x64-based Systems Service Pack 2 Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation) Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
fullName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
finalName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1 Version 6.1 / NT 6.1",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
fullName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
finalName: "Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation) Version 6.1 / NT 6.1",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1803 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1803 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1803 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server, version 1803 (Server Core Installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
fullName: "Windows Server, version 1803 (Server Core Installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
finalName: "Windows Server, version 1803 (Server Core Installation)",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1809 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2019",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
fullName: "Windows Server 2019",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
finalName: "Windows Server 2019 Version 1809",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2019 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
fullName: "Windows Server 2019 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2019",
|
||||
finalName: "Windows Server 2019 (Server Core installation) Version 1809",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1709 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1709 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1709 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1903 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1903 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1903 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server, version 1903 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
fullName: "Windows Server, version 1903 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
finalName: "Windows Server, version 1903 (Server Core installation)",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1607 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2016",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
fullName: "Windows Server 2016",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
finalName: "Windows Server 2016 Version 1607",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2016 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
fullName: "Windows Server 2016 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2016",
|
||||
finalName: "Windows Server 2016 (Server Core installation) Version 1607",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 8.1 for x64-based systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 8.1",
|
||||
fullName: "Windows 8.1 for x64-based systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 8.1",
|
||||
finalName: "Windows 8.1 for x64-based systems Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
fullName: "Windows Server 2012",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
finalName: "Windows Server 2012 Version 6.2 / NT 6.2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
fullName: "Windows Server 2012 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012",
|
||||
finalName: "Windows Server 2012 (Server Core installation) Version 6.2 / NT 6.2",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 R2",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
fullName: "Windows Server 2012 R2",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
finalName: "Windows Server 2012 R2 Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2012 R2 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
fullName: "Windows Server 2012 R2 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server 2012 R2",
|
||||
finalName: "Windows Server 2012 R2 (Server Core installation) Version 6.3 / NT 6.3",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
arch: "64-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1909 for x64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server, version 1909 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
fullName: "Windows Server, version 1909 (Server Core installation)",
|
||||
arch: "all",
|
||||
prodName: "Windows Server",
|
||||
finalName: "Windows Server, version 1909 (Server Core installation)",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1803 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1803 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1803 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1803 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1803 for ARM64-based Systems",
|
||||
arch: "arm64",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1803 for ARM64-based Systems",
|
||||
},
|
||||
{
|
||||
fullName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
fullName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows 10",
|
||||
finalName: "Windows 10 Version 1809 for 32-bit Systems",
|
||||
},
|
||||
{
|
||||
fullName: "None Available",
|
||||
arch: "all",
|
||||
prodName: "",
|
||||
fullName: "None Available",
|
||||
arch: "all",
|
||||
prodName: "",
|
||||
finalName: "None Available",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)",
|
||||
arch: "32-bit",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation) Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 for Itanium-Based Systems Service Pack 2",
|
||||
arch: "itanium",
|
||||
prodName: "Windows Server 2008",
|
||||
fullName: "Windows Server 2008 for Itanium-Based Systems Service Pack 2",
|
||||
arch: "itanium",
|
||||
prodName: "Windows Server 2008",
|
||||
finalName: "Windows Server 2008 for Itanium-Based Systems Service Pack 2 Version 6.0 / NT 6.0",
|
||||
},
|
||||
{
|
||||
fullName: "Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1",
|
||||
arch: "itanium",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
fullName: "Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1",
|
||||
arch: "itanium",
|
||||
prodName: "Windows Server 2008 R2",
|
||||
finalName: "Windows Server 2008 R2 for Itanium-Based Systems Service Pack 1 Version 6.1 / NT 6.1",
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -429,6 +499,7 @@ func TestFullProductName(t *testing.T) {
|
|||
for _, tCase := range testCases {
|
||||
sut := NewProductFromFullName(tCase.fullName)
|
||||
require.Equal(t, tCase.prodName, sut.Name(), tCase)
|
||||
require.Equal(t, tCase.finalName, string(sut), tCase)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package parsed
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
"golang.org/x/exp/slices"
|
||||
"os"
|
||||
)
|
||||
|
||||
type SecurityBulletin struct {
|
||||
|
|
@ -45,6 +46,9 @@ func UnmarshalBulletin(fPath string) (*SecurityBulletin, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for pID, name := range bulletin.Products {
|
||||
bulletin.Products[pID] = NewProductFromFullName(string(name))
|
||||
}
|
||||
return &bulletin, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func TestParser(t *testing.T) {
|
|||
f.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
// All the products we expect to see, grouped by their product name
|
||||
// All the products we expect to see after marshaling, grouped by their product name.
|
||||
expectedProducts := map[string]parsed.Products{
|
||||
"Windows 10": {
|
||||
"11568": parsed.NewProductFromFullName("Windows 10 Version 1809 for 32-bit Systems"),
|
||||
|
|
@ -112,6 +112,79 @@ func TestParser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
// All the products we expect to see in the parsed XML file, grouped by product name.
|
||||
expectedXMLProducts := map[string]parsed.Products{
|
||||
"Windows 10": {
|
||||
"11568": parsed.Product("Windows 10 Version 1809 for 32-bit Systems"),
|
||||
"11569": parsed.Product("Windows 10 Version 1809 for x64-based Systems"),
|
||||
"11570": parsed.Product("Windows 10 Version 1809 for ARM64-based Systems"),
|
||||
"11712": parsed.Product("Windows 10 Version 1909 for 32-bit Systems"),
|
||||
"11713": parsed.Product("Windows 10 Version 1909 for x64-based Systems"),
|
||||
"11714": parsed.Product("Windows 10 Version 1909 for ARM64-based Systems"),
|
||||
"11896": parsed.Product("Windows 10 Version 21H1 for x64-based Systems"),
|
||||
"11897": parsed.Product("Windows 10 Version 21H1 for ARM64-based Systems"),
|
||||
"11898": parsed.Product("Windows 10 Version 21H1 for 32-bit Systems"),
|
||||
"11800": parsed.Product("Windows 10 Version 20H2 for x64-based Systems"),
|
||||
"11801": parsed.Product("Windows 10 Version 20H2 for 32-bit Systems"),
|
||||
"11802": parsed.Product("Windows 10 Version 20H2 for ARM64-based Systems"),
|
||||
"11929": parsed.Product("Windows 10 Version 21H2 for 32-bit Systems"),
|
||||
"11930": parsed.Product("Windows 10 Version 21H2 for ARM64-based Systems"),
|
||||
"11931": parsed.Product("Windows 10 Version 21H2 for x64-based Systems"),
|
||||
"10729": parsed.Product("Windows 10 for 32-bit Systems"),
|
||||
"10735": parsed.Product("Windows 10 for x64-based Systems"),
|
||||
"10852": parsed.Product("Windows 10 Version 1607 for 32-bit Systems"),
|
||||
"10853": parsed.Product("Windows 10 Version 1607 for x64-based Systems"),
|
||||
},
|
||||
"Windows Server 2019": {
|
||||
"11571": parsed.Product("Windows Server 2019"),
|
||||
"11572": parsed.Product("Windows Server 2019 (Server Core installation)"),
|
||||
},
|
||||
"Windows Server 2022": {
|
||||
"11923": parsed.Product("Windows Server 2022"),
|
||||
"11924": parsed.Product("Windows Server 2022 (Server Core installation)"),
|
||||
},
|
||||
"Windows Server": {
|
||||
"11803": parsed.Product("Windows Server, version 20H2 (Server Core Installation)"),
|
||||
},
|
||||
"Windows 11": {
|
||||
"11926": parsed.Product("Windows 11 for x64-based Systems"),
|
||||
"11927": parsed.Product("Windows 11 for ARM64-based Systems"),
|
||||
},
|
||||
"Windows Server 2016": {
|
||||
"10816": parsed.Product("Windows Server 2016"),
|
||||
"10855": parsed.Product("Windows Server 2016 (Server Core installation)"),
|
||||
},
|
||||
"Windows 8.1": {
|
||||
"10481": parsed.Product("Windows 8.1 for 32-bit systems"),
|
||||
"10482": parsed.Product("Windows 8.1 for x64-based systems"),
|
||||
},
|
||||
"Windows RT 8.1": {
|
||||
"10484": parsed.Product("Windows RT 8.1"),
|
||||
},
|
||||
"Windows Server 2012": {
|
||||
"10378": parsed.Product("Windows Server 2012"),
|
||||
"10379": parsed.Product("Windows Server 2012 (Server Core installation)"),
|
||||
},
|
||||
"Windows Server 2012 R2": {
|
||||
"10483": parsed.Product("Windows Server 2012 R2"),
|
||||
"10543": parsed.Product("Windows Server 2012 R2 (Server Core installation)"),
|
||||
},
|
||||
"Windows 7": {
|
||||
"10047": parsed.Product("Windows 7 for 32-bit Systems Service Pack 1"),
|
||||
"10048": parsed.Product("Windows 7 for x64-based Systems Service Pack 1"),
|
||||
},
|
||||
"Windows Server 2008": {
|
||||
"9312": parsed.Product("Windows Server 2008 for 32-bit Systems Service Pack 2"),
|
||||
"10287": parsed.Product("Windows Server 2008 for 32-bit Systems Service Pack 2 (Server Core installation)"),
|
||||
"9318": parsed.Product("Windows Server 2008 for x64-based Systems Service Pack 2"),
|
||||
"9344": parsed.Product("Windows Server 2008 for x64-based Systems Service Pack 2 (Server Core installation)"),
|
||||
},
|
||||
"Windows Server 2008 R2": {
|
||||
"10051": parsed.Product("Windows Server 2008 R2 for x64-based Systems Service Pack 1"),
|
||||
"10049": parsed.Product("Windows Server 2008 R2 for x64-based Systems Service Pack 1 (Server Core installation)"),
|
||||
},
|
||||
}
|
||||
|
||||
expectedCVEs := map[string][]string{
|
||||
"Windows 10": {
|
||||
"CVE-2022-30190",
|
||||
|
|
@ -1213,7 +1286,7 @@ func TestParser(t *testing.T) {
|
|||
t.Run("parseXML", func(t *testing.T) {
|
||||
t.Run("only windows products are included", func(t *testing.T) {
|
||||
var expected []msrcxml.Product
|
||||
for _, grp := range expectedProducts {
|
||||
for _, grp := range expectedXMLProducts {
|
||||
for pID, pFn := range grp {
|
||||
expected = append(
|
||||
expected,
|
||||
|
|
|
|||
BIN
website/assets/images/permanent/mastodon-logo-50x40@2x.png
vendored
Normal file
BIN
website/assets/images/permanent/mastodon-logo-50x40@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
38
website/assets/styles/pages/testimonials.less
vendored
38
website/assets/styles/pages/testimonials.less
vendored
|
|
@ -100,6 +100,34 @@
|
|||
}
|
||||
}
|
||||
|
||||
[purpose='section-headline'] {
|
||||
padding-top: 64px;
|
||||
padding-bottom: 64px;
|
||||
p {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
[purpose='articles'] {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
[purpose='article-link'] {
|
||||
padding-top: 24px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid var(--Fleet-Black-10, #E2E4EA);
|
||||
[parasails-component='animated-arrow-button'] {
|
||||
width: fit-content;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
font-weight: 700;
|
||||
[purpose='button-text'] {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[purpose='testimonials-container'] {
|
||||
columns: 3;
|
||||
margin-bottom: 32px;
|
||||
|
|
@ -427,6 +455,16 @@
|
|||
height: 304px;
|
||||
}
|
||||
}
|
||||
[purpose='section-headline'] {
|
||||
padding-top: 32px;
|
||||
padding-bottom: 32px;
|
||||
p {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
[purpose='articles'] {
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
[purpose='statistics'] {
|
||||
[purpose='statistics-column'] {
|
||||
display: flex;
|
||||
|
|
|
|||
26
website/views/pages/testimonials.ejs
vendored
26
website/views/pages/testimonials.ejs
vendored
|
|
@ -112,6 +112,32 @@
|
|||
</div>
|
||||
</div>
|
||||
<div purpose="page-section">
|
||||
<div purpose="section-headline">
|
||||
<h2>Case strudies</h2>
|
||||
<p>Real-world stories of why the community and customers love Fleet.</p>
|
||||
</div>
|
||||
<div purpose="articles">
|
||||
<div purpose="articles">
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/consolidate-multiple-tools-with-fleet">🥀 Leading financial company consolidates multiple tools with Fleet</animated-arrow-button>
|
||||
</div>
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/global-cloud-platform-simplifies-device-management-with-fleet">🪟 Global edge cloud platform simplifies device management with Fleet</animated-arrow-button>
|
||||
</div>
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/worldwide-security-and-authentication-platform-chooses-fleet-for-linux">🚪 Worldwide security and authentication platform chooses Fleet for Linux management</animated-arrow-button>
|
||||
</div>
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/large-gaming-company-enhances-server-observability-with-fleet">🔌 Large gaming company enhances server observability with Fleet</animated-arrow-button>
|
||||
</div>
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/vehicle-manufacturer-transitions-to-fleet-for-endpoint-security">🚪 Vehicle manufacturer transitions to Fleet for endpoint security</animated-arrow-button>
|
||||
</div>
|
||||
<div purpose="article-link">
|
||||
<animated-arrow-button arrow-color="#3E4771" class="w-100" href="/announcements/foursquare-quickly-migrates-to-fleet">🚪 Foursquare quickly migrates to Fleet for Device Management</animated-arrow-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-row align-items-center justify-content-center">
|
||||
<a purpose="share-button" href="https://github.com/fleetdm/fleet/edit/main/handbook/company/testimonials.yml" target="_blank">Share your story</a>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue