diff --git a/.yarnrc b/.yarnrc
new file mode 100644
index 0000000000..fdd705c635
--- /dev/null
+++ b/.yarnrc
@@ -0,0 +1 @@
+save-prefix ""
diff --git a/assets/images/os-prefill-preview.gif b/assets/images/os-prefill-preview.gif
new file mode 100644
index 0000000000..21fcc0693a
Binary files /dev/null and b/assets/images/os-prefill-preview.gif differ
diff --git a/changes/17018-reset-query-report b/changes/17018-reset-query-report
new file mode 100644
index 0000000000..444fac3f8b
--- /dev/null
+++ b/changes/17018-reset-query-report
@@ -0,0 +1 @@
+- Query report is reset when there is a change to the selected platform or selected minimum osquery version
diff --git a/changes/17264-batch-process-gitops b/changes/17264-batch-process-gitops
new file mode 100644
index 0000000000..cfa7ce9776
--- /dev/null
+++ b/changes/17264-batch-process-gitops
@@ -0,0 +1 @@
+- `fleetctl gitops` now batch processes queries and policies
\ No newline at end of file
diff --git a/changes/17265-filter-alignment b/changes/17265-filter-alignment
new file mode 100644
index 0000000000..a27c775810
--- /dev/null
+++ b/changes/17265-filter-alignment
@@ -0,0 +1 @@
+* Fix a small alignment bug
diff --git a/changes/17559-batch-set-duplicate-mdm b/changes/17559-batch-set-duplicate-mdm
new file mode 100644
index 0000000000..f037326fff
--- /dev/null
+++ b/changes/17559-batch-set-duplicate-mdm
@@ -0,0 +1 @@
+- Added cross-platform check for duplicate MDM profiles names in batch set MDM profiles API.
diff --git a/changes/17621-bulk-delete-hosts-all-teams b/changes/17621-bulk-delete-hosts-all-teams
new file mode 100644
index 0000000000..ed210b1655
--- /dev/null
+++ b/changes/17621-bulk-delete-hosts-all-teams
@@ -0,0 +1 @@
+- Fix UI's ability to bulk delete hosts when "All teams" is selected
diff --git a/changes/17927-fix-styling-for-live-query-disabled-warning b/changes/17927-fix-styling-for-live-query-disabled-warning
new file mode 100644
index 0000000000..42323137fb
--- /dev/null
+++ b/changes/17927-fix-styling-for-live-query-disabled-warning
@@ -0,0 +1 @@
+- UI fix: styling of live query disabled warning
diff --git a/cmd/fleet/calendar_cron.go b/cmd/fleet/calendar_cron.go
index 953747c602..54bd89f551 100644
--- a/cmd/fleet/calendar_cron.go
+++ b/cmd/fleet/calendar_cron.go
@@ -17,6 +17,8 @@ import (
"github.com/go-kit/log/level"
)
+const calendarConsumers = 18
+
func newCalendarSchedule(
ctx context.Context,
instanceID string,
@@ -200,11 +202,10 @@ func processCalendarFailingHosts(
) {
hosts = filterHostsWithSameEmail(hosts)
- const consumers = 20
hostsCh := make(chan fleet.HostPolicyMembershipData)
var wg sync.WaitGroup
- for i := 0; i < consumers; i++ {
+ for i := 0; i < calendarConsumers; i++ {
wg.Add(+1)
go func() {
defer wg.Done()
@@ -500,11 +501,10 @@ func removeCalendarEventsFromPassingHosts(
})
}
- const consumers = 20
emailsCh := make(chan emailWithHosts)
var wg sync.WaitGroup
- for i := 0; i < consumers; i++ {
+ for i := 0; i < calendarConsumers; i++ {
wg.Add(+1)
go func() {
defer wg.Done()
@@ -601,15 +601,16 @@ func cronCalendarEventsCleanup(ctx context.Context, ds fleet.Datastore, logger k
}
var userCalendar fleet.UserCalendar
+ var calendarConfig *fleet.GoogleCalendarIntegration
if len(appConfig.Integrations.GoogleCalendar) > 0 {
- googleCalendarIntegrationConfig := appConfig.Integrations.GoogleCalendar[0]
- userCalendar = createUserCalendarFromConfig(ctx, googleCalendarIntegrationConfig, logger)
+ calendarConfig = appConfig.Integrations.GoogleCalendar[0]
+ userCalendar = createUserCalendarFromConfig(ctx, calendarConfig, logger)
}
// If global setting is disabled, we remove all calendar events from the DB
// (we cannot delete the events from the user calendar because there's no configuration anymore).
if userCalendar == nil {
- if err := deleteAllCalendarEvents(ctx, ds, nil, nil); err != nil {
+ if err := deleteAllCalendarEvents(ctx, ds, nil, nil, logger); err != nil {
return fmt.Errorf("delete all calendar events: %w", err)
}
// We've deleted all calendar events, nothing else to do.
@@ -630,7 +631,7 @@ func cronCalendarEventsCleanup(ctx context.Context, ds fleet.Datastore, logger k
}
for _, team := range teams {
- if err := cleanupTeamCalendarEvents(ctx, ds, userCalendar, *team); err != nil {
+ if err := cleanupTeamCalendarEvents(ctx, ds, calendarConfig, *team, logger); err != nil {
level.Info(logger).Log("msg", "delete team calendar events", "team_id", team.ID, "err", err)
}
}
@@ -644,38 +645,59 @@ func cronCalendarEventsCleanup(ctx context.Context, ds fleet.Datastore, logger k
if err != nil {
return fmt.Errorf("list out of date calendar events: %w", err)
}
- for _, outOfDateCalendarEvent := range outOfDateCalendarEvents {
- if err := deleteCalendarEvent(ctx, ds, userCalendar, outOfDateCalendarEvent); err != nil {
- return fmt.Errorf("delete user calendar event: %w", err)
- }
- }
-
+ deleteCalendarEventsInParallel(ctx, ds, calendarConfig, outOfDateCalendarEvents, logger)
return nil
}
func deleteAllCalendarEvents(
ctx context.Context,
ds fleet.Datastore,
- userCalendar fleet.UserCalendar,
+ calendarConfig *fleet.GoogleCalendarIntegration,
teamID *uint,
+ logger kitlog.Logger,
) error {
calendarEvents, err := ds.ListCalendarEvents(ctx, teamID)
if err != nil {
return fmt.Errorf("list calendar events: %w", err)
}
- for _, calendarEvent := range calendarEvents {
- if err := deleteCalendarEvent(ctx, ds, userCalendar, calendarEvent); err != nil {
- return fmt.Errorf("delete user calendar event: %w", err)
- }
- }
+ deleteCalendarEventsInParallel(ctx, ds, calendarConfig, calendarEvents, logger)
return nil
}
+func deleteCalendarEventsInParallel(
+ ctx context.Context, ds fleet.Datastore, calendarConfig *fleet.GoogleCalendarIntegration, calendarEvents []*fleet.CalendarEvent,
+ logger kitlog.Logger,
+) {
+ if len(calendarEvents) > 0 {
+ calendarEventCh := make(chan *fleet.CalendarEvent)
+ var wg sync.WaitGroup
+ for i := 0; i < calendarConsumers; i++ {
+ wg.Add(+1)
+ go func() {
+ defer wg.Done()
+ for calEvent := range calendarEventCh {
+ userCalendar := createUserCalendarFromConfig(ctx, calendarConfig, logger)
+ if err := deleteCalendarEvent(ctx, ds, userCalendar, calEvent); err != nil {
+ level.Error(logger).Log("msg", "delete user calendar event", "err", err)
+ continue
+ }
+ }
+ }()
+ }
+ for _, outOfDateCalendarEvent := range calendarEvents {
+ calendarEventCh <- outOfDateCalendarEvent
+ }
+ close(calendarEventCh)
+ wg.Wait()
+ }
+}
+
func cleanupTeamCalendarEvents(
ctx context.Context,
ds fleet.Datastore,
- userCalendar fleet.UserCalendar,
+ calendarConfig *fleet.GoogleCalendarIntegration,
team fleet.Team,
+ logger kitlog.Logger,
) error {
teamFeatureEnabled := team.Config.Integrations.GoogleCalendar != nil && team.Config.Integrations.GoogleCalendar.Enable
@@ -692,7 +714,7 @@ func cleanupTeamCalendarEvents(
// so we want to cleanup all calendar events for the team.
}
- return deleteAllCalendarEvents(ctx, ds, userCalendar, &team.ID)
+ return deleteAllCalendarEvents(ctx, ds, calendarConfig, &team.ID, logger)
}
func deleteCalendarEvent(ctx context.Context, ds fleet.Datastore, userCalendar fleet.UserCalendar, calendarEvent *fleet.CalendarEvent) error {
diff --git a/cmd/fleetctl/mdm_test.go b/cmd/fleetctl/mdm_test.go
index d275e15aab..0a7062de30 100644
--- a/cmd/fleetctl/mdm_test.go
+++ b/cmd/fleetctl/mdm_test.go
@@ -101,8 +101,10 @@ func TestMDMRunCommand(t *testing.T) {
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("Pending")},
}
hostByUUID := make(map[string]*fleet.Host)
+ hostByID := make(map[uint]*fleet.Host)
for _, h := range []*fleet.Host{macEnrolled, winEnrolled, macUnenrolled, winUnenrolled, linuxUnenrolled, macEnrolled2, winEnrolled2, macNonFleetEnrolled, winNonFleetEnrolled, macPending, winPending} {
hostByUUID[h.UUID] = h
+ hostByID[h.ID] = h
}
// define some files to use in the tests
@@ -221,6 +223,15 @@ func TestMDMRunCommand(t *testing.T) {
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
return &fleet.HostMDMDiskEncryption{}, nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostByID[hostID]
+ require.True(t, ok)
+ if h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+ return h.MDMInfo, nil
+ }
+
enqueuer.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
return map[string]error{}, nil
}
@@ -467,6 +478,15 @@ func TestMDMLockCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
@@ -701,6 +721,15 @@ func TestMDMUnlockCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
@@ -1001,6 +1030,15 @@ func TestMDMWipeCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
appCfgScriptsDisabled := &fleet.AppConfig{ServerSettings: fleet.ServerSettings{ScriptsDisabled: true}}
diff --git a/cmd/osquery-perf/agent.go b/cmd/osquery-perf/agent.go
index 756f6f0cd5..611bcfe702 100644
--- a/cmd/osquery-perf/agent.go
+++ b/cmd/osquery-perf/agent.go
@@ -401,7 +401,7 @@ type agent struct {
// single goroutine at a time can execute scripts.
scriptExecRunning atomic.Bool
- softwareVSCodeExtensionsProb float64
+ softwareQueryFailureProb float64
softwareVSCodeExtensionsFailProb float64
//
@@ -544,7 +544,7 @@ func newAgent(
UUID: hostUUID,
SerialNumber: serialNumber,
- softwareVSCodeExtensionsProb: softwareQueryFailureProb,
+ softwareQueryFailureProb: softwareQueryFailureProb,
softwareVSCodeExtensionsFailProb: softwareVSCodeExtensionsQueryFailureProb,
macMDMClient: macMDMClient,
@@ -1737,7 +1737,7 @@ func (a *agent) processQuery(name, query string) (
return true, results, &ss, nil, nil
case name == hostDetailQueryPrefix+"software_macos":
ss := fleet.StatusOK
- if a.softwareVSCodeExtensionsProb > 0.0 && rand.Float64() <= a.softwareVSCodeExtensionsProb {
+ if a.softwareQueryFailureProb > 0.0 && rand.Float64() <= a.softwareQueryFailureProb {
ss = fleet.OsqueryStatus(1)
}
if ss == fleet.StatusOK {
@@ -1746,7 +1746,7 @@ func (a *agent) processQuery(name, query string) (
return true, results, &ss, nil, nil
case name == hostDetailQueryPrefix+"software_windows":
ss := fleet.StatusOK
- if a.softwareVSCodeExtensionsProb > 0.0 && rand.Float64() <= a.softwareVSCodeExtensionsProb {
+ if a.softwareQueryFailureProb > 0.0 && rand.Float64() <= a.softwareQueryFailureProb {
ss = fleet.OsqueryStatus(1)
}
if ss == fleet.StatusOK {
@@ -1755,7 +1755,7 @@ func (a *agent) processQuery(name, query string) (
return true, results, &ss, nil, nil
case name == hostDetailQueryPrefix+"software_linux":
ss := fleet.StatusOK
- if a.softwareVSCodeExtensionsProb > 0.0 && rand.Float64() <= a.softwareVSCodeExtensionsProb {
+ if a.softwareQueryFailureProb > 0.0 && rand.Float64() <= a.softwareQueryFailureProb {
ss = fleet.OsqueryStatus(1)
}
if ss == fleet.StatusOK {
@@ -2019,8 +2019,8 @@ func main() {
onlyAlreadyEnrolled = flag.Bool("only_already_enrolled", false, "Only start agents that are already enrolled")
nodeKeyFile = flag.String("node_key_file", "", "File with node keys to use")
- softwareQueryFailureProb = flag.Float64("software_query_fail_prob", 0.5, "Probability of the software query failing")
- softwareVSCodeExtensionsQueryFailureProb = flag.Float64("software_vscode_extensions_query_fail_prob", 0.5, "Probability of the software vscode_extensions query failing")
+ softwareQueryFailureProb = flag.Float64("software_query_fail_prob", 0.05, "Probability of the software query failing")
+ softwareVSCodeExtensionsQueryFailureProb = flag.Float64("software_vscode_extensions_query_fail_prob", 0.05, "Probability of the software vscode_extensions query failing")
commonSoftwareCount = flag.Int("common_software_count", 10, "Number of common installed applications reported to fleet")
commonVSCodeExtensionsSoftwareCount = flag.Int("common_vscode_extensions_software_count", 5, "Number of common vscode_extensions installed applications reported to fleet")
diff --git a/docs/Get started/FAQ.md b/docs/Get started/FAQ.md
index 9f7d76edd4..aaacfd3813 100644
--- a/docs/Get started/FAQ.md
+++ b/docs/Get started/FAQ.md
@@ -113,7 +113,7 @@ To uninstall the osquery agent, follow the below instructions for your operating
Run the Orbit [cleanup script](https://github.com/fleetdm/fleet/blob/main/orbit/tools/cleanup/cleanup_macos.sh)
#### Windows
-Use the "Add or remove programs" dialog to remove Orbit.
+Use the "Add or remove programs" dialog to remove Fleet osquery.
#### Ubuntu
Run `sudo apt remove fleet-osquery -y`
diff --git a/docs/REST API/rest-api.md b/docs/REST API/rest-api.md
index 2358f62050..39ea5b88c1 100644
--- a/docs/REST API/rest-api.md
+++ b/docs/REST API/rest-api.md
@@ -7373,10 +7373,10 @@ This allows you to easily configure scheduled queries that will impact a whole t
- [Run script](#run-script)
- [Get script result](#get-script-result)
- [Run live script](#run-live-script)
-- [Upload a script](#upload-a-script)
-- [Delete a script](#delete-a-script)
+- [Add script](#add-script)
+- [Delete script](#delete-script)
- [List scripts](#list-scripts)
-- [Get or download a script](#get-or-download-a-script)
+- [Get or download script](#get-or-download-script)
- [Get script details by host](#get-script-details-by-host)
### Run script
@@ -7488,7 +7488,7 @@ Run a live script and get results back (5 minute timeout). Live scripts only run
}
```
-### Upload a script
+### Add script
Uploads a script, making it available to run on hosts assigned to the specified team (or no team).
@@ -7538,7 +7538,7 @@ echo "hello"
}
```
-### Delete a script
+### Delete script
Deletes an existing script.
@@ -7566,6 +7566,7 @@ Deletes an existing script.
| Name | Type | In | Description |
| --------------- | ------- | ----- | ----------------------------------------------------------------------------------------------------------------------------- |
+| team_id | integer | query | _Available in Fleet Premium_. The ID of the team to filter scripts by. If not specified, it will filter only scripts that are available to hosts with no team. |
| page | integer | query | Page number of the results to fetch. |
| per_page | integer | query | Results per page. |
@@ -7603,7 +7604,7 @@ Deletes an existing script.
```
-### Get or download a script
+### Get or download script
`GET /api/v1/fleet/scripts/:id`
@@ -7614,7 +7615,7 @@ Deletes an existing script.
| id | integer | path | **Required.** The desired script's ID. |
| alt | string | query | If specified and set to "media", downloads the script's contents. |
-#### Example (get a script)
+#### Example (get script)
`GET /api/v1/fleet/scripts/123`
@@ -7633,7 +7634,7 @@ Deletes an existing script.
```
-#### Example (download a script's contents)
+#### Example (download script)
`GET /api/v1/fleet/scripts/123?alt=media`
diff --git a/docs/Using Fleet/CIS-Benchmarks.md b/docs/Using Fleet/CIS-Benchmarks.md
index 1bcbb2e1fc..9942eb0e3c 100644
--- a/docs/Using Fleet/CIS-Benchmarks.md
+++ b/docs/Using Fleet/CIS-Benchmarks.md
@@ -2,8 +2,6 @@
_Available in Fleet Premium_.
-## Overview
-
CIS Benchmarks represent the consensus-based effort of cybersecurity experts globally to help you protect your systems against threats more confidently.
For more information about CIS Benchmarks check out [Center for Internet Security](https://www.cisecurity.org/cis-benchmarks)'s website.
@@ -46,22 +44,6 @@ Two things are being evaluated in this policy:
If either of these conditions fails, the host is considered to be failing the policy.
-## Requirements
-
-Following are the requirements to use the CIS Benchmarks in Fleet:
-
-- To use these policies, Fleet must have an up-to-date paid license (β₯Fleet Premium).
-- Devices must be running [`fleetd`](https://fleetdm.com/docs/using-fleet/orbit), the lightweight agent that bundles the latest osqueryd.
-- Some CIS Benchmarks explicitly involve verifying MDM-based controls, so devices must be enrolled to an MDM solution. (Any MDM solution works, it doesn't have to be Fleet.)
-- On macOS, the orbit executable in Fleetd must have "Full Disk Access", see [Grant Full Disk Access to Osquery on macOS](./Adding-hosts.md#grant-full-disk-access-to-osquery-on-macos).
-
-### MDM required
-Some of the policies created by Fleet use the [managed_policies](https://www.fleetdm.com/tables/managed_policies) table. This checks whether an MDM solution has turned on the setting to enforce the policy.
-Using MDM is the recommended way to manage and enforce CIS Benchmarks. To learn how to set up MDM in Fleet, visit [here](/docs/using-fleet/mdm-macos-setup).
-
-### Fleetd required
-Fleet's CIS Benchmarks require our [osquery manager, Fleetd](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer). This is because Fleetd includes tables which are not part of vanilla osquery in order to accomplish auditing the benchmarks.
-
## How to add CIS Benchmarks
All CIS policies are stored under our restricted licensed folder `ee/cis/`.
@@ -89,25 +71,6 @@ To apply the policies on a specific team use the `--policies-team` flag:
fleetctl apply --policies-team "Workstations" -f cis-policy-queries.yml
```
-## Limitations
-
-Certain benchmarks require human action to audit, and cannot be automated by a policy in Fleet. For a list of specific benchmarks which are not covered, please visit the README for each benchmark:
-
-- [macOS 13.0 Ventura](https://github.com/fleetdm/fleet/blob/main/ee/cis/macos-13/README.md)
-- [macOS 14.0 Sonoma](https://github.com/fleetdm/fleet/blob/main/ee/cis/macos-14/README.md)
-- [Windows 10 Enterprise](https://github.com/fleetdm/fleet/blob/main/ee/cis/win-10/README.md)
-- [Windows 11 Enterprise](https://github.com/fleetdm/fleet/blob/main/ee/cis/win-11/README.md)
-
-### Audit vs. remediation
-Each benchmark has two elements:
-1. Audit - how to find out whether the host is in compliance with the benchmark
-2. Remediation - if the host is out of compliance with the benchmark, how to fix it
-
-Since Fleetd is currently read-only without the ability to execute actions on the host, Fleet does not implement the remediation portions of CIS benchmarks.
-
-To implement automated remediation, you can install a separate agent such as Munki, Chef, Puppet, etc. which has write functionality.
-
-
## Levels 1 and 2
CIS designates various benchmarks as Level 1 or Level 2 to describe the level of thoroughness and burden that each benchmark represents.
@@ -126,6 +89,22 @@ This profile extends the "Level 1" profile. Items in this profile exhibit one or
- are intended for environments or use cases where security is paramount or acts as defense in depth measure
- may negatively inhibit the utility or performance of the technology.
+## Requirements
+
+Following are the requirements to use the CIS Benchmarks in Fleet:
+
+- Devices must be running [`fleetd`](https://fleetdm.com/docs/using-fleet/orbit), Fleet's lightweight agent.
+- Some CIS Benchmarks explicitly involve verifying MDM-based controls, so devices must be enrolled to an MDM solution.
+- On macOS, the orbit component of fleetd must have "Full Disk Access", see [Grant Full Disk Access to Osquery on macOS](./Adding-hosts.md#grant-full-disk-access-to-osquery-on-macos).
+
+## Limitations
+
+Certain benchmarks cannot be automated by a policy in Fleet. For a list of specific benchmarks which are not covered, please visit the README for each benchmark:
+
+- [macOS 13.0 Ventura](https://github.com/fleetdm/fleet/blob/main/ee/cis/macos-13/README.md)
+- [macOS 14.0 Sonoma](https://github.com/fleetdm/fleet/blob/main/ee/cis/macos-14/README.md)
+- [Windows 10 Enterprise](https://github.com/fleetdm/fleet/blob/main/ee/cis/win-10/README.md)
+- [Windows 11 Enterprise](https://github.com/fleetdm/fleet/blob/main/ee/cis/win-11/README.md)
## Performance testing
In August 2023, we completed scale testing on 10k Windows hosts and 70k macOS hosts. Ultimately, we validated both server and host performance at that scale.
diff --git a/docs/Using Fleet/enroll-hosts.md b/docs/Using Fleet/enroll-hosts.md
index e0b2545f03..81e852cbb6 100644
--- a/docs/Using Fleet/enroll-hosts.md
+++ b/docs/Using Fleet/enroll-hosts.md
@@ -123,7 +123,7 @@ How to unenroll a host from Fleet:
## Advanced
-
+- [Fleet agent (fleetd) components](#fleetd-components)
- [Signing fleetd installer](#signing-fleetd-installer)
- [Grant full disk access to osquery on macOS](#grant-full-disk-access-to-osquery-on-macos)
- [Using mTLS](#using-mtls)
@@ -134,6 +134,25 @@ How to unenroll a host from Fleet:
- [Generating Windows installers using local WiX toolset](#generating-windows-installers-using-local-wix-toolset)
- [Experimental features](#experimental-features)
+### fleetd components
+
+```mermaid
+graph LR;
+ tuf["TUF file server
(default: tuf.fleetctl.com)"];
+ fleet_server[Fleet
Server];
+ subgraph fleetd
+ orbit[orbit];
+ desktop[Fleet Desktop
Tray App];
+ osqueryd[osqueryd];
+ desktop_browser[Fleet Desktop
from Browser];
+ end
+ orbit -- "Fleet Orbit API (TLS)" --> fleet_server;
+ desktop -- "Fleet Desktop API (TLS)" --> fleet_server;
+ osqueryd -- "osquery
remote API (TLS)" --> fleet_server;
+ desktop_browser -- "My Device API (TLS)" --> fleet_server;
+ orbit -- "Auto Update (TLS)" --> tuf;
+```
+
### Signing fleetd installers
>**Note:** Currently, the `fleetctl package` command does not support signing Windows fleetd installers. Windows installers can be signed after building.
diff --git a/docs/Using Fleet/fleetctl-CLI.md b/docs/Using Fleet/fleetctl-CLI.md
index 678dbd565e..d83702e46e 100644
--- a/docs/Using Fleet/fleetctl-CLI.md
+++ b/docs/Using Fleet/fleetctl-CLI.md
@@ -120,15 +120,14 @@ An API-only user does not have access to the Fleet UI. Instead, it's only purpos
### Create API-only user
+Before creating the API-only user, log in to `fleetctl` as an admin. See [authentication](https://#authentication) above for details.
+
To create your new API-only user, use `fleetctl user create`:
```sh
fleetctl user create --name "API User" --email api@example.com --password temp@pass123 --api-only
```
-
-To use fleetctl with an API-only user, you will need to log in via `fleetctl`. See [authentication](https://#authentication) above for details.
-
#### Permissions
An API-only user can be given the same permissions as a regular user. The default access level is **Observer**. You can specify what level of access the new user should have using the `--global-role` flag:
diff --git a/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx b/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
index 3bc7998618..4d88395155 100644
--- a/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
+++ b/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
@@ -60,7 +60,7 @@ const LogDestinationIndicator = ({
return (
<>
Each time a query runs, the data is sent to
- Amazon Kinesis Data Firehose.`
+ Amazon Kinesis Data Firehose.
>
);
case "kinesis":
@@ -81,7 +81,7 @@ const LogDestinationIndicator = ({
return (
<>
Each time a query runs, the data is
sent to Google Cloud Pub
- / Sub.`
+ / Sub.
>
);
case "kafta":
diff --git a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
index a3941ac7af..9998278692 100644
--- a/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
+++ b/frontend/pages/DashboardPage/cards/ActivityFeed/ActivityItem/ActivityItem.tsx
@@ -799,10 +799,8 @@ const TAGGED_TEMPLATES = {
return (
<>
{" "}
- edited declaration (DDM) profile
- {activity.details?.profile_name}
- {" "}
- for{" "}
+ edited declaration (DDM) profiles{" "}
+ {activity.details?.profile_name} for{" "}
{getProfileMessageSuffix(
isPremiumTier,
"darwin",
diff --git a/frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/components/SetupAssistantPreview/SetupAssistantPreview.tsx b/frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/components/SetupAssistantPreview/SetupAssistantPreview.tsx
index 9e080644d6..d67255a6c2 100644
--- a/frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/components/SetupAssistantPreview/SetupAssistantPreview.tsx
+++ b/frontend/pages/ManageControlsPage/SetupExperience/cards/SetupAssistant/components/SetupAssistantPreview/SetupAssistantPreview.tsx
@@ -2,7 +2,7 @@ import React from "react";
import Card from "components/Card";
-import OsSetupPreview from "../../../../../../../../assets/images/os-setup-preview.gif";
+import OsPrefillPreview from "../../../../../../../../assets/images/os-prefill-preview.gif";
const baseClass = "setup-assistant-preview";
@@ -25,7 +25,7 @@ const SetupAssistantPreview = () => {
5. Configure your service account integration in Fleet using the - form below: + form below.
- Fleet is unable to run a live query. Refresh the page or log in
- again. If this keeps happening please{" "}
-