mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
Merge contents of 7766-frontend and main, all conflicts resolved (#14429)
This commit is contained in:
commit
1cb4121842
281 changed files with 19191 additions and 2944 deletions
|
|
@ -72,7 +72,6 @@ go.mod @fleetdm/go
|
|||
#
|
||||
# (see website/config/custom.js for DRIs of other paths not listed here)
|
||||
##############################################################################################
|
||||
/website/views/pages/pricing.ejs @mikermcneil # « CEO is DRI for pricing
|
||||
/handbook/company/pricing-features-table.yml @mikermcneil # « CEO is current DRI for features table
|
||||
|
||||
##############################################################################################
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Fleet 4.37.0 | Remote script execution & Puppet support.
|
||||
# Fleet 4.37.0 | Puppet support.
|
||||
|
||||

|
||||
|
||||
|
|
@ -13,11 +13,12 @@ For upgrade instructions, see our [upgrade guide](https://fleetdm.com/docs/deplo
|
|||
* Puppet support
|
||||
* Web user interface improvements
|
||||
|
||||
<!--
|
||||
### Introducing cross-platform script execution
|
||||
|
||||
_Available in Fleet Premium and Fleet Ultimate_
|
||||
|
||||
Fleet adds a significant new feature, allowing IT administrators and security engineers to execute shell scripts across macOS, Windows, and Linux. This addition streamlines processes, offers root-level security control, and enables swift, real-time remediation and investigation. Learn more about Fleet's [cross-platform script execution](introducing-cross-platform-script-execution).
|
||||
Fleet adds a significant new feature, allowing IT administrators and security engineers to execute shell scripts across macOS, Windows, and Linux. This addition streamlines processes, offers root-level security control, and enables swift, real-time remediation and investigation. <!-- Learn more about Fleet's [cross-platform script execution](introducing-cross-platform-script-execution). -->
|
||||
|
||||
|
||||
### Vulnerability dashboard
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 14 KiB |
1
changes/12927-disk-encryption-settings
Normal file
1
changes/12927-disk-encryption-settings
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Deprecate `mdm.macos_settings.enable_disk_encryption` in favor of `mdm.enable_disk_encryption`
|
||||
4
changes/12932-bitlocker-api-updates
Normal file
4
changes/12932-bitlocker-api-updates
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
- Added `GET /mdm/disk_encryption/summary` endpoint to get the disk encryption summary for macOS and
|
||||
Windows devices.
|
||||
- Added `os_settings` and `os_settings_disk_encryption` filters to `GET /hosts`, `GET /hosts/count`,
|
||||
`GET /api/v1/fleet/labels/{id}/hosts` endpoints to filter hosts by OS settings.
|
||||
1
changes/12933-bitlocker-host-details-api
Normal file
1
changes/12933-bitlocker-host-details-api
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Added `mdm.os_settings` to `GET /api/v1/hosts/{id}` response.
|
||||
1
changes/14286-detail-query-overrides
Normal file
1
changes/14286-detail-query-overrides
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Fixed a bug that would cause live queries to stall if a detail query override was set for a team.
|
||||
1
changes/bug-13894-failing-policies-styling
Normal file
1
changes/bug-13894-failing-policies-styling
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Fix styling for host details/device user failing policies call out
|
||||
|
|
@ -0,0 +1 @@
|
|||
- change Controls/Disk Encryption and host details page to include windows bitlocker information.
|
||||
1
changes/issue-13954-orbit-disk-encryption-key
Normal file
1
changes/issue-13954-orbit-disk-encryption-key
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Added the `POST /api/fleet/orbit/disk_encryption_key` endpoint for Windows hosts to report the bitlocker encryption key.
|
||||
1
changes/issue-14007-support-get-windows-encryption-key
Normal file
1
changes/issue-14007-support-get-windows-encryption-key
Normal file
|
|
@ -0,0 +1 @@
|
|||
* Added support to return the decrypted disk encryption key of a Windows host.
|
||||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/fleetdm/fleet/v4/server/contexts/license"
|
||||
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/mdm"
|
||||
apple_mdm "github.com/fleetdm/fleet/v4/server/mdm/apple"
|
||||
"github.com/fleetdm/fleet/v4/server/policies"
|
||||
"github.com/fleetdm/fleet/v4/server/ptr"
|
||||
|
|
@ -852,7 +853,7 @@ func verifyDiskEncryptionKeys(
|
|||
if key.UpdatedAt.After(latest) {
|
||||
latest = key.UpdatedAt
|
||||
}
|
||||
if _, err := apple_mdm.DecryptBase64CMS(key.Base64Encrypted, cert.Leaf, cert.PrivateKey); err != nil {
|
||||
if _, err := mdm.DecryptBase64CMS(key.Base64Encrypted, cert.Leaf, cert.PrivateKey); err != nil {
|
||||
undecryptable = append(undecryptable, key.HostID)
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1043,13 +1043,13 @@ spec:
|
|||
foo: qux
|
||||
name: Team1
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_updates:
|
||||
minimum_version: 10.10.10
|
||||
deadline: 1992-03-01
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
- %s
|
||||
enable_disk_encryption: false
|
||||
secrets:
|
||||
- secret: BBB
|
||||
`, mobileConfigPath))
|
||||
|
|
@ -1061,9 +1061,9 @@ spec:
|
|||
require.Equal(t, "[+] applied 1 teams\n", runAppForTest(t, []string{"apply", "-f", name}))
|
||||
assert.JSONEq(t, string(json.RawMessage(`{"config":{"views":{"foo":"qux"}}}`)), string(*savedTeam.Config.AgentOptions))
|
||||
assert.Equal(t, fleet.TeamMDM{
|
||||
EnableDiskEncryption: false,
|
||||
MacOSSettings: fleet.MacOSSettings{
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
EnableDiskEncryption: false,
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
},
|
||||
MacOSUpdates: fleet.MacOSUpdates{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
|
|
@ -1096,9 +1096,9 @@ spec:
|
|||
require.True(t, ds.NewJobFuncInvoked)
|
||||
// all left untouched, only setup assistant added
|
||||
assert.Equal(t, fleet.TeamMDM{
|
||||
EnableDiskEncryption: false,
|
||||
MacOSSettings: fleet.MacOSSettings{
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
EnableDiskEncryption: false,
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
},
|
||||
MacOSUpdates: fleet.MacOSUpdates{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
|
|
@ -1128,9 +1128,9 @@ spec:
|
|||
require.Equal(t, "[+] applied 1 teams\n", runAppForTest(t, []string{"apply", "-f", name}))
|
||||
// all left untouched, only bootstrap package added
|
||||
assert.Equal(t, fleet.TeamMDM{
|
||||
EnableDiskEncryption: false,
|
||||
MacOSSettings: fleet.MacOSSettings{
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
EnableDiskEncryption: false,
|
||||
CustomSettings: []string{mobileConfigPath},
|
||||
},
|
||||
MacOSUpdates: fleet.MacOSUpdates{
|
||||
MinimumVersion: optjson.SetString("10.10.10"),
|
||||
|
|
@ -2885,7 +2885,7 @@ spec:
|
|||
macos_settings:
|
||||
enable_disk_encryption: true
|
||||
`,
|
||||
wantErr: `Couldn't update macos_settings because MDM features aren't turned on in Fleet.`,
|
||||
wantErr: `Couldn't edit enable_disk_encryption. Neither macOS MDM nor Windows is turned on`,
|
||||
},
|
||||
{
|
||||
desc: "app config macos_settings.enable_disk_encryption false",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/fleetdm/fleet/v4/pkg/rawjson"
|
||||
"github.com/fleetdm/fleet/v4/pkg/secure"
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
"github.com/fleetdm/fleet/v4/server/service"
|
||||
|
|
@ -166,12 +167,15 @@ func (eacp enrichedAppConfigPresenter) MarshalJSON() ([]byte, error) {
|
|||
*fleet.VulnerabilitiesConfig
|
||||
}
|
||||
|
||||
return json.Marshal(&struct {
|
||||
fleet.EnrichedAppConfig
|
||||
enrichedJSON, err := json.Marshal(fleet.EnrichedAppConfig(eacp))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extraFieldsJSON, err := json.Marshal(&struct {
|
||||
UpdateInterval UpdateIntervalConfigPresenter `json:"update_interval,omitempty"`
|
||||
Vulnerabilities VulnerabilitiesConfigPresenter `json:"vulnerabilities,omitempty"`
|
||||
}{
|
||||
EnrichedAppConfig: fleet.EnrichedAppConfig(eacp),
|
||||
UpdateInterval: UpdateIntervalConfigPresenter{
|
||||
eacp.UpdateInterval.OSQueryDetail.String(),
|
||||
eacp.UpdateInterval.OSQueryPolicy.String(),
|
||||
|
|
@ -183,6 +187,13 @@ func (eacp enrichedAppConfigPresenter) MarshalJSON() ([]byte, error) {
|
|||
eacp.Vulnerabilities,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// we need to marshal and combine both groups separately because
|
||||
// enrichedAppConfig has a custom marshaler.
|
||||
return rawjson.CombineRoots(enrichedJSON, extraFieldsJSON)
|
||||
}
|
||||
|
||||
func printConfig(c *cli.Context, config interface{}) error {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -168,15 +167,15 @@ func TestGetTeams(t *testing.T) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(filepath.Join("testdata", "expectedGetTeamsText.txt"))
|
||||
b, err := os.ReadFile(filepath.Join("testdata", "expectedGetTeamsText.txt"))
|
||||
require.NoError(t, err)
|
||||
expectedText := string(b)
|
||||
|
||||
b, err = ioutil.ReadFile(filepath.Join("testdata", "expectedGetTeamsYaml.yml"))
|
||||
b, err = os.ReadFile(filepath.Join("testdata", "expectedGetTeamsYaml.yml"))
|
||||
require.NoError(t, err)
|
||||
expectedYaml := string(b)
|
||||
|
||||
b, err = ioutil.ReadFile(filepath.Join("testdata", "expectedGetTeamsJson.json"))
|
||||
b, err = os.ReadFile(filepath.Join("testdata", "expectedGetTeamsJson.json"))
|
||||
require.NoError(t, err)
|
||||
// must read each JSON value separately and compact it
|
||||
var buf bytes.Buffer
|
||||
|
|
@ -206,8 +205,8 @@ func TestGetTeams(t *testing.T) {
|
|||
errBuffer.Reset()
|
||||
actualJSON, err := runWithErrWriter([]string{"get", "teams", "--json"}, &errBuffer)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedJson, actualJSON.String())
|
||||
require.Equal(t, errBuffer.String() == expiredBanner.String(), tt.shouldHaveExpiredBanner)
|
||||
require.Equal(t, expectedJson, actualJSON.String())
|
||||
|
||||
errBuffer.Reset()
|
||||
actualYaml, err := runWithErrWriter([]string{"get", "teams", "--yaml"}, &errBuffer)
|
||||
|
|
@ -433,7 +432,7 @@ func TestGetHosts(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
expected, err := ioutil.ReadFile(filepath.Join("testdata", tt.goldenFile))
|
||||
expected, err := os.ReadFile(filepath.Join("testdata", tt.goldenFile))
|
||||
require.NoError(t, err)
|
||||
expectedResults := tt.scanner(string(expected))
|
||||
actualResult := tt.scanner(runAppForTest(t, tt.args))
|
||||
|
|
@ -536,7 +535,7 @@ func TestGetHostsMDM(t *testing.T) {
|
|||
}
|
||||
|
||||
if tt.goldenFile != "" {
|
||||
expected, err := ioutil.ReadFile(filepath.Join("testdata", tt.goldenFile))
|
||||
expected, err := os.ReadFile(filepath.Join("testdata", tt.goldenFile))
|
||||
require.NoError(t, err)
|
||||
if ext := filepath.Ext(tt.goldenFile); ext == ".json" {
|
||||
// the output of --json is not a json array, but a list of
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
"enabled_and_configured": false,
|
||||
"apple_bm_default_team": "",
|
||||
"windows_enabled_and_configured": false,
|
||||
"enable_disk_encryption": false,
|
||||
"macos_updates": {
|
||||
"minimum_version": null,
|
||||
"deadline": null
|
||||
|
|
@ -96,8 +97,7 @@
|
|||
"webhook_url": ""
|
||||
},
|
||||
"macos_settings": {
|
||||
"custom_settings": null,
|
||||
"enable_disk_encryption": false
|
||||
"custom_settings": null
|
||||
},
|
||||
"macos_setup": {
|
||||
"bootstrap_package": null,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ spec:
|
|||
enabled_and_configured: false
|
||||
apple_bm_default_team: ""
|
||||
windows_enabled_and_configured: false
|
||||
enable_disk_encryption: false
|
||||
macos_migration:
|
||||
enable: false
|
||||
mode: ""
|
||||
|
|
@ -28,7 +29,6 @@ spec:
|
|||
deadline: null
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package:
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
"apple_bm_enabled_and_configured": false,
|
||||
"enabled_and_configured": false,
|
||||
"windows_enabled_and_configured": false,
|
||||
"enable_disk_encryption": false,
|
||||
"macos_updates": {
|
||||
"minimum_version": null,
|
||||
"deadline": null
|
||||
|
|
@ -54,8 +55,7 @@
|
|||
"webhook_url": ""
|
||||
},
|
||||
"macos_settings": {
|
||||
"custom_settings": null,
|
||||
"enable_disk_encryption": false
|
||||
"custom_settings": null
|
||||
},
|
||||
"macos_setup": {
|
||||
"bootstrap_package": null,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ spec:
|
|||
apple_bm_terms_expired: false
|
||||
enabled_and_configured: false
|
||||
windows_enabled_and_configured: false
|
||||
enable_disk_encryption: false
|
||||
macos_migration:
|
||||
enable: false
|
||||
mode: ""
|
||||
|
|
@ -28,7 +29,6 @@ spec:
|
|||
deadline: null
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package:
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
"enable_software_inventory": true
|
||||
},
|
||||
"mdm": {
|
||||
"enable_disk_encryption": false,
|
||||
"macos_updates": {
|
||||
"minimum_version": null,
|
||||
"deadline": null
|
||||
},
|
||||
"macos_settings": {
|
||||
"custom_settings": null,
|
||||
"enable_disk_encryption": false
|
||||
"custom_settings": null
|
||||
},
|
||||
"macos_setup": {
|
||||
"bootstrap_package": null,
|
||||
|
|
@ -84,13 +84,13 @@
|
|||
}
|
||||
},
|
||||
"mdm": {
|
||||
"enable_disk_encryption": false,
|
||||
"macos_updates": {
|
||||
"minimum_version": "12.3.1",
|
||||
"deadline": "2021-12-14"
|
||||
},
|
||||
"macos_settings": {
|
||||
"custom_settings": null,
|
||||
"enable_disk_encryption": false
|
||||
"custom_settings": null
|
||||
},
|
||||
"macos_setup": {
|
||||
"bootstrap_package": null,
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ spec:
|
|||
enable_host_users: true
|
||||
enable_software_inventory: true
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_updates:
|
||||
minimum_version: null
|
||||
deadline: null
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package:
|
||||
enable_end_user_authentication: false
|
||||
|
|
@ -36,12 +36,12 @@ spec:
|
|||
enable_host_users: false
|
||||
enable_software_inventory: false
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_updates:
|
||||
minimum_version: "12.3.1"
|
||||
deadline: "2021-12-14"
|
||||
macos_settings:
|
||||
custom_settings:
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package:
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ spec:
|
|||
apple_bm_terms_expired: false
|
||||
enabled_and_configured: true
|
||||
windows_enabled_and_configured: false
|
||||
enable_disk_encryption: false
|
||||
macos_migration:
|
||||
enable: false
|
||||
mode: ""
|
||||
webhook_url: ""
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: null
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ spec:
|
|||
apple_bm_terms_expired: false
|
||||
enabled_and_configured: true
|
||||
windows_enabled_and_configured: false
|
||||
enable_disk_encryption: false
|
||||
macos_migration:
|
||||
enable: false
|
||||
mode: ""
|
||||
webhook_url: ""
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: %s
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ spec:
|
|||
enable_host_users: true
|
||||
enable_software_inventory: true
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: null
|
||||
enable_end_user_authentication: false
|
||||
|
|
@ -27,9 +27,9 @@ spec:
|
|||
enable_host_users: true
|
||||
enable_software_inventory: true
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: null
|
||||
macos_setup_assistant: null
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ spec:
|
|||
enable_host_users: true
|
||||
enable_software_inventory: true
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: %s
|
||||
enable_end_user_authentication: false
|
||||
|
|
@ -27,9 +27,9 @@ spec:
|
|||
enable_host_users: false
|
||||
enable_software_inventory: false
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: %s
|
||||
macos_setup_assistant: %s
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ spec:
|
|||
enable_host_users: false
|
||||
enable_software_inventory: false
|
||||
mdm:
|
||||
enable_disk_encryption: false
|
||||
macos_settings:
|
||||
custom_settings: null
|
||||
enable_disk_encryption: false
|
||||
macos_setup:
|
||||
bootstrap_package: null
|
||||
enable_end_user_authentication: false
|
||||
|
|
|
|||
|
|
@ -529,8 +529,10 @@ Use with caution as this may break Fleet ingestion of hosts data.
|
|||
```yaml
|
||||
features:
|
||||
detail_query_overrides:
|
||||
# null allows to disable the "users" query from running on hosts.
|
||||
# null disables the "users" query from running on hosts.
|
||||
users: null
|
||||
# "" disables the "disk_encryption_linux" query from running on hosts.
|
||||
disk_encryption_linux: ""
|
||||
# this replaces the hardcoded "mdm" detail query.
|
||||
mdm: "SELECT enrolled, server_url, installed_from_dep, payload_identifier FROM mdm;"
|
||||
```
|
||||
|
|
|
|||
|
|
@ -533,6 +533,7 @@ The MDM endpoints exist to support the related command-line interface sub-comman
|
|||
- [Complete SSO during DEP enrollment](#complete-sso-during-dep-enrollment)
|
||||
- [Preassign profiles to devices](#preassign-profiles-to-devices)
|
||||
- [Match preassigned profiles](#match-preassigned-profiles)
|
||||
- [Get FileVault statistics](#get-filevault-statistics)
|
||||
|
||||
### Generate Apple DEP Key Pair
|
||||
|
||||
|
|
@ -701,6 +702,44 @@ This endpoint stores a profile to be assigned to a host at some point in the fut
|
|||
|
||||
`Status: 204`
|
||||
|
||||
### Get FileVault statistics
|
||||
|
||||
_Available in Fleet Premium_
|
||||
|
||||
Get aggregate status counts of disk encryption enforced on macOS hosts.
|
||||
|
||||
The summary can optionally be filtered by team id.
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/filevault/summary`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | string | query | _Available in Fleet Premium_ The team id to filter the summary. |
|
||||
|
||||
#### Example
|
||||
|
||||
Get aggregate status counts of Apple disk encryption profiles applying to macOS hosts enrolled to Fleet's MDM that are not assigned to any team.
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/filevault/summary`
|
||||
|
||||
##### Default response
|
||||
|
||||
`Status: 200`
|
||||
|
||||
```json
|
||||
{
|
||||
"verified": 123,
|
||||
"verifying": 123,
|
||||
"action_required": 123,
|
||||
"enforcing": 123,
|
||||
"failed": 123,
|
||||
"removing_enforcement": 123
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Match preassigned profiles
|
||||
|
||||
_Available in Fleet Premium_
|
||||
|
|
@ -2291,7 +2330,9 @@ Gets all information required by Fleet Desktop, this includes things like the nu
|
|||
{
|
||||
"failing_policies_count": 3,
|
||||
"notifications": {
|
||||
"needs_mdm_migration": true
|
||||
"needs_mdm_migration": true,
|
||||
"renew_enrollment_profile": false,
|
||||
"enforce_bitlocker_encryption": false,
|
||||
},
|
||||
"config": {
|
||||
"org_info": {
|
||||
|
|
@ -2313,6 +2354,7 @@ In regards to the `notifications` key:
|
|||
|
||||
- `needs_mdm_migration` means that the device fits all the requirements to allow the user to initiate an MDM migration to Fleet.
|
||||
- `renew_enrollment_profile` means that the device is currently unmanaged from MDM but should be DEP enrolled into Fleet.
|
||||
- `enforce_bitlocker_encryption` applies only to Windows devices and means that it should encrypt the disk and report the encryption key back to Fleet.
|
||||
|
||||
|
||||
#### Get device's policies
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ If you also have Fleetd running on hosts, it will need access to these API endpo
|
|||
* `/api/fleet/orbit/ping`
|
||||
* `/api/fleet/orbit/scripts/request`
|
||||
* `/api/fleet/orbit/scripts/result`
|
||||
* `/api/fleet/orbit/disk_encryption_key`
|
||||
* `/api/osquery/log`
|
||||
|
||||
<meta name="description" value="Find commonly asked questions and answers about contributing to Fleet as part of our community.">
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Fleetctl (pronouced “fleet control”) is a CLI (command line interface) tool
|
|||
|
||||
## Fleetd
|
||||
|
||||
Fleetd is a bundle of agents provided by Fleet to gather information about your devices. Fleetd includes [osquery](https://www.osquery.io/), Orbit, and Fleet Desktop. [Docs](https://fleetdm.com/docs/using-fleet/fleet-ui).
|
||||
Fleetd is a bundle of agents provided by Fleet to gather information about your devices. Fleetd includes [osquery](https://www.osquery.io/), Orbit, and Fleet Desktop. [Docs](https://fleetdm.com/docs/using-fleet/fleetd).
|
||||
|
||||
## Osquery
|
||||
Osquery is an open-source tool for gathering information about the state of any device that the osquery agent has been installed on. [Learn more](https://www.osquery.io/).
|
||||
|
|
|
|||
|
|
@ -1829,14 +1829,14 @@ the `software` table.
|
|||
| page | integer | query | Page number of the results to fetch. |
|
||||
| per_page | integer | query | Results per page. |
|
||||
| order_key | string | query | What to order results by. Can be any column in the hosts table. |
|
||||
| after | string | query | The value to get results after. This needs `order_key` defined, as that's the column that would be used. **Note:** Use `page` instead of `after`. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be `new`, `online`, `offline`, `mia` or `missing`. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, `ipv4` and the hosts' email addresses (only searched if the query looks like an email address, i.e. contains an `@`, no space, etc.). |
|
||||
| additional_info_filters | string | query | A comma-delimited list of fields to include in each host's additional information object. See [Fleet Configuration Options](https://fleetdm.com/docs/using-fleet/fleetctl-cli#fleet-configuration-options) for an example configuration with hosts' additional information. Use `*` to get all stored fields. |
|
||||
| after | string | query | The value to get results after. This needs `order_key` defined, as that's the column that would be used. **Note:** Use `page` instead of `after` |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include 'asc' and 'desc'. Default is 'asc'. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be 'new', 'online', 'offline', 'mia' or 'missing'. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, `ipv4` and the hosts' email addresses (only searched if the query looks like an email address, i.e. contains an '@', no space, etc.). |
|
||||
| additional_info_filters | string | query | A comma-delimited list of fields to include in each host's additional information object. See [Fleet Configuration Options](https://fleetdm.com/docs/using-fleet/fleetctl-cli#fleet-configuration-options) for an example configuration with hosts' additional information. Use '*' to get all stored fields. |
|
||||
| team_id | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts in the specified team. |
|
||||
| policy_id | integer | query | The ID of the policy to filter hosts by. |
|
||||
| policy_response | string | query | Valid options are `passing` or `failing`. `policy_id` must also be specified with `policy_response`. |
|
||||
| policy_response | string | query | Valid options are 'passing' or 'failing'. `policy_id` must also be specified with `policy_response`. |
|
||||
| software_id | integer | query | The ID of the software to filter hosts by. |
|
||||
| os_id | integer | query | The ID of the operating system to filter hosts by. |
|
||||
| os_name | string | query | The name of the operating system to filter hosts by. `os_version` must also be specified with `os_name` |
|
||||
|
|
@ -1845,7 +1845,7 @@ the `software` table.
|
|||
| mdm_id | integer | query | The ID of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider and URL). |
|
||||
| mdm_name | string | query | The name of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider). |
|
||||
| mdm_enrollment_status | string | query | The _mobile device management_ (MDM) enrollment status to filter hosts by. Can be one of 'manual', 'automatic', 'enrolled', 'pending', or 'unenrolled'. |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team id filter, the results include only hosts that are not assigned to any team.** |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team ID filter, the results include only hosts that are not assigned to any team.** |
|
||||
| munki_issue_id | integer | query | The ID of the _munki issue_ (a Munki-reported error or warning message) to filter hosts by (that is, filter hosts that are affected by that corresponding error or warning message). |
|
||||
| low_disk_space | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts with less GB of disk space available than this value. Must be a number between 1-100. |
|
||||
| disable_failing_policies| boolean | query | If "true", hosts will return failing policies as 0 regardless of whether there are any that failed for the host. This is meant to be used when increased performance is needed in exchange for the extra information. |
|
||||
|
|
@ -1858,9 +1858,9 @@ If `software_id` is specified, an additional top-level key `"software"` is retur
|
|||
|
||||
If `mdm_id` is specified, an additional top-level key `"mobile_device_management_solution"` is returned with the information corresponding to the `mdm_id`.
|
||||
|
||||
If `mdm_id`, `mdm_name` or `mdm_enrollment_status` is specified, then Windows Servers are excluded from the results.
|
||||
If `mdm_id`, `mdm_name`, `mdm_enrollment_status`, `os_settings`, or `os_settings_disk_encryption` is specified, then Windows Servers are excluded from the results.
|
||||
|
||||
If `munki_issue_id` is specified, an additional top-level key `"munki_issue"` is returned with the information corresponding to the `munki_issue_id`.
|
||||
If `munki_issue_id` is specified, an additional top-level key `munki_issue` is returned with the information corresponding to the `munki_issue_id`.
|
||||
|
||||
If `after` is being used with `created_at` or `updated_at`, the table must be specified in `order_key`. Those columns become `h.created_at` and `h.updated_at`.
|
||||
|
||||
|
|
@ -1988,13 +1988,13 @@ Response payload with the `munki_issue_id` filter provided:
|
|||
| Name | Type | In | Description |
|
||||
| ----------------------- | ------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| order_key | string | query | What to order results by. Can be any column in the hosts table. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include 'asc' and 'desc'. Default is 'asc'. |
|
||||
| after | string | query | The value to get results after. This needs `order_key` defined, as that's the column that would be used. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be `new`, `online`, `offline`, `mia` or `missing`. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, `ipv4` and the hosts' email addresses (only searched if the query looks like an email address, i.e. contains an `@`, no space, etc.). |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be 'new', 'online', 'offline', 'mia' or 'missing'. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, `ipv4` and the hosts' email addresses (only searched if the query looks like an email address, i.e. contains an '@', no space, etc.). |
|
||||
| team_id | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts in the specified team. |
|
||||
| policy_id | integer | query | The ID of the policy to filter hosts by. |
|
||||
| policy_response | string | query | Valid options are `passing` or `failing`. `policy_id` must also be specified with `policy_response`. |
|
||||
| policy_response | string | query | Valid options are 'passing' or 'failing'. `policy_id` must also be specified with `policy_response`. |
|
||||
| software_id | integer | query | The ID of the software to filter hosts by. |
|
||||
| os_id | integer | query | The ID of the operating system to filter hosts by. |
|
||||
| os_name | string | query | The name of the operating system to filter hosts by. `os_version` must also be specified with `os_name` |
|
||||
|
|
@ -2003,7 +2003,7 @@ Response payload with the `munki_issue_id` filter provided:
|
|||
| mdm_id | integer | query | The ID of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider and URL). |
|
||||
| mdm_name | string | query | The name of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider). |
|
||||
| mdm_enrollment_status | string | query | The _mobile device management_ (MDM) enrollment status to filter hosts by. Can be one of 'manual', 'automatic', 'enrolled', 'pending', or 'unenrolled'. |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team id filter, the results include only hosts that are not assigned to any team.** |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team ID filter, the results include only hosts that are not assigned to any team.** |
|
||||
| munki_issue_id | integer | query | The ID of the _munki issue_ (a Munki-reported error or warning message) to filter hosts by (that is, filter hosts that are affected by that corresponding error or warning message). |
|
||||
| low_disk_space | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts with less GB of disk space available than this value. Must be a number between 1-100. |
|
||||
| macos_settings_disk_encryption | string | query | Filters the hosts by the status of the macOS disk encryption MDM profile on the host. Can be one of `verified`, `verifying`, `action_required`, `enforcing`, `failed`, or `removing_enforcement`. |
|
||||
|
|
@ -2555,6 +2555,9 @@ Returns the information of the host specified using the `uuid`, `osquery_host_id
|
|||
"bootstrap_package_status": "installed",
|
||||
"detail": ""
|
||||
},
|
||||
"os_settings": {
|
||||
"disk_encryption": null
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": 999,
|
||||
|
|
@ -2743,6 +2746,9 @@ This is the API route used by the **My device** page in Fleet desktop to display
|
|||
"detail": "",
|
||||
"bootstrap_package_name": "test.pkg"
|
||||
},
|
||||
"os_settings": {
|
||||
"disk_encryption": null
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": 999,
|
||||
|
|
@ -3291,12 +3297,12 @@ requested by a web browser.
|
|||
| format | string | query | **Required**, must be "csv" (only supported format for now). |
|
||||
| columns | string | query | Comma-delimited list of columns to include in the report (returns all columns if none is specified). |
|
||||
| order_key | string | query | What to order results by. Can be any column in the hosts table. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be `new`, `online`, `offline`, `mia` or `missing`. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include 'asc' and 'desc'. Default is 'asc'. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be 'new', 'online', 'offline', 'mia' or 'missing'. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, `ipv4` and the hosts' email addresses (only searched if the query looks like an email address, i.e. contains an `@`, no space, etc.). |
|
||||
| team_id | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts in the specified team. |
|
||||
| policy_id | integer | query | The ID of the policy to filter hosts by. |
|
||||
| policy_response | string | query | Valid options are `passing` or `failing`. `policy_id` must also be specified with `policy_response`. **Note: If `policy_id` is specified _without_ including `policy_response`, this will also return hosts where the policy is not configured to run or failed to run.** |
|
||||
| policy_response | string | query | Valid options are 'passing' or 'failing'. `policy_id` must also be specified with `policy_response`. **Note: If `policy_id` is specified _without_ including `policy_response`, this will also return hosts where the policy is not configured to run or failed to run.** |
|
||||
| software_id | integer | query | The ID of the software to filter hosts by. |
|
||||
| os_id | integer | query | The ID of the operating system to filter hosts by. |
|
||||
| os_name | string | query | The name of the operating system to filter hosts by. `os_version` must also be specified with `os_name` |
|
||||
|
|
@ -3304,7 +3310,7 @@ requested by a web browser.
|
|||
| mdm_id | integer | query | The ID of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider and URL). |
|
||||
| mdm_name | string | query | The name of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider). |
|
||||
| mdm_enrollment_status | string | query | The _mobile device management_ (MDM) enrollment status to filter hosts by. Can be one of 'manual', 'automatic', 'enrolled', 'pending', or 'unenrolled'. |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team id filter, the results include only hosts that are not assigned to any team.** |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team ID filter, the results include only hosts that are not assigned to any team.** |
|
||||
| munki_issue_id | integer | query | The ID of the _munki issue_ (a Munki-reported error or warning message) to filter hosts by (that is, filter hosts that are affected by that corresponding error or warning message). |
|
||||
| low_disk_space | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts with less GB of disk space available than this value. Must be a number between 1-100. |
|
||||
| label_id | integer | query | A valid label ID. Can only be used in combination with `order_key`, `order_direction`, `status`, `query` and `team_id`. |
|
||||
|
|
@ -3330,7 +3336,7 @@ created_at,updated_at,id,detail_updated_at,label_updated_at,policy_updated_at,la
|
|||
|
||||
### Get host's disk encryption key
|
||||
|
||||
Requires the [macadmins osquery extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
For macOS, requires the [macadmins osquery extension](https://github.com/macadmins/osquery-extension) which comes bundled
|
||||
in [Fleet's osquery installers](https://fleetdm.com/docs/using-fleet/adding-hosts#osquery-installer).
|
||||
|
||||
Requires Fleet's MDM properly [enabled and configured](https://fleetdm.com/docs/using-fleet/mdm-macos-setup).
|
||||
|
|
@ -3724,21 +3730,21 @@ Returns a list of the hosts that belong to the specified label.
|
|||
| page | integer | query | Page number of the results to fetch. |
|
||||
| per_page | integer | query | Results per page. |
|
||||
| order_key | string | query | What to order results by. Can be any column in the hosts table. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include `asc` and `desc`. Default is `asc`. |
|
||||
| order_direction | string | query | **Requires `order_key`**. The direction of the order given the order key. Options include 'asc' and 'desc'. Default is 'asc'. |
|
||||
| after | string | query | The value to get results after. This needs `order_key` defined, as that's the column that would be used. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be `new`, `online`, `offline`, `mia` or `missing`. |
|
||||
| status | string | query | Indicates the status of the hosts to return. Can either be 'new', 'online', 'offline', 'mia' or 'missing'. |
|
||||
| query | string | query | Search query keywords. Searchable fields include `hostname`, `machine_serial`, `uuid`, and `ipv4`. |
|
||||
| team_id | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts in the specified team. |
|
||||
| disable_failing_policies | boolean | query | If "true", hosts will return failing policies as 0 regardless of whether there are any that failed for the host. This is meant to be used when increased performance is needed in exchange for the extra information. |
|
||||
| mdm_id | integer | query | The ID of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider and URL). |
|
||||
| mdm_name | string | query | The name of the _mobile device management_ (MDM) solution to filter hosts by (that is, filter hosts that use a specific MDM provider). |
|
||||
| mdm_enrollment_status | string | query | The _mobile device management_ (MDM) enrollment status to filter hosts by. Can be one of 'manual', 'automatic', 'enrolled', 'pending', or 'unenrolled'. |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team id filter, the results include only hosts that are not assigned to any team.** |
|
||||
| macos_settings | string | query | Filters the hosts by the status of the _mobile device management_ (MDM) profiles applied to hosts. Can be one of 'verified', 'verifying', 'pending', or 'failed'. **Note: If this filter is used in Fleet Premium without a team ID filter, the results include only hosts that are not assigned to any team.** |
|
||||
| low_disk_space | integer | query | _Available in Fleet Premium_ Filters the hosts to only include hosts with less GB of disk space available than this value. Must be a number between 1-100. |
|
||||
| macos_settings_disk_encryption | string | query | Filters the hosts by the status of the macOS disk encryption MDM profile on the host. Can be one of `verified`, `verifying`, `action_required`, `enforcing`, `failed`, or `removing_enforcement`. |
|
||||
| bootstrap_package | string | query | _Available in Fleet Premium_ Filters the hosts by the status of the MDM bootstrap package on the host. Can be one of `installed`, `pending`, or `failed`. **Note: If this filter is used in Fleet Premium without a team id filter, the results include only hosts that are not assigned to any team.** |
|
||||
|
||||
If `mdm_id`, `mdm_name` or `mdm_enrollment_status` is specified, then Windows Servers are excluded from the results.
|
||||
If `mdm_id`, `mdm_name`, `mdm_enrollment_status`, `os_settings`, or `os_settings_disk_encryption` is specified, then Windows Servers are excluded from the results.
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -3887,8 +3893,8 @@ Add a configuration profile to enforce custom settings on macOS hosts.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | -------- | ---- | ------------------------------------------------------------------------- |
|
||||
| profile | file | form | **Required**. The mobileconfig file containing the profile. |
|
||||
| team_id | string | form | _Available in Fleet Premium_ The team id for the profile. If specified, the profile is applied to only hosts that are assigned to the specified team. If not specified, the profile is applied to only to hosts that are not assigned to any team. |
|
||||
| profile | file | form | **Required**. The .mobileconfig file containing the profile. |
|
||||
| team_id | string | form | _Available in Fleet Premium_ The team ID for the profile. If specified, the profile is applied to only hosts that are assigned to the specified team. If not specified, the profile is applied to only to hosts that are not assigned to any team. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -3967,7 +3973,7 @@ results (i.e., only profiles that are associated with "No team" are listed).
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | string | query | _Available in Fleet Premium_ The team id to filter profiles. |
|
||||
| team_id | string | query | _Available in Fleet Premium_ The team ID to filter profiles. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -4090,11 +4096,11 @@ _Available in Fleet Premium_
|
|||
|
||||
_Available in Fleet Premium_
|
||||
|
||||
Get aggregate status counts of disk encryption enforced on hosts.
|
||||
Get aggregate status counts of disk encryption enforced on macOS and Windows hosts.
|
||||
|
||||
The summary can optionally be filtered by team id.
|
||||
The summary can optionally be filtered by team ID.
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/filevault/summary`
|
||||
`GET /api/v1/fleet/mdm/disk_encryption/summary`
|
||||
|
||||
#### Parameters
|
||||
|
||||
|
|
@ -4104,9 +4110,9 @@ The summary can optionally be filtered by team id.
|
|||
|
||||
#### Example
|
||||
|
||||
Get aggregate status counts of Apple disk encryption profiles applying to macOS hosts enrolled to Fleet's MDM that are not assigned to any team.
|
||||
Get aggregate disk encryption status counts of macOS and Windows hosts enrolled to Fleet's MDM that are not assigned to any team.
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/filevault/summary`
|
||||
`GET /api/v1/fleet/mdm/disk_encryption/summary`
|
||||
|
||||
##### Default response
|
||||
|
||||
|
|
@ -4114,12 +4120,12 @@ Get aggregate status counts of Apple disk encryption profiles applying to macOS
|
|||
|
||||
```json
|
||||
{
|
||||
"verified": 123,
|
||||
"verifying": 123,
|
||||
"action_required": 123,
|
||||
"enforcing": 123,
|
||||
"failed": 123,
|
||||
"removing_enforcement": 123
|
||||
"verified": {"macos": 123, "windows": 123},
|
||||
"verifying": {"macos": 123, "windows": 0},
|
||||
"action_required": {"macos": 123, "windows": 0},
|
||||
"enforcing": {"macos": 123, "windows": 123},
|
||||
"failed": {"macos": 123, "windows": 123},
|
||||
"removing_enforcement": {"macos": 123, "windows": 0},
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -4128,7 +4134,7 @@ Get aggregate status counts of Apple disk encryption profiles applying to macOS
|
|||
Get aggregate status counts of all macOS settings (configuraiton profiles and disk encryption) enforced on hosts.
|
||||
|
||||
For Fleet Premium uses, the statistics can
|
||||
optionally be filtered by team id. If no team id is specified, team profiles are excluded from the
|
||||
optionally be filtered by team ID. If no team ID is specified, team profiles are excluded from the
|
||||
results (i.e., only profiles that are associated with "No team" are listed).
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/profiles/summary`
|
||||
|
|
@ -4137,7 +4143,7 @@ results (i.e., only profiles that are associated with "No team" are listed).
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | string | query | _Available in Fleet Premium_ The team id to filter profiles. |
|
||||
| team_id | string | query | _Available in Fleet Premium_ The team ID to filter profiles. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -4274,7 +4280,7 @@ Sets the custom MDM setup enrollment profile for a team or no team.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | integer | json | The team id this custom enrollment profile applies to, or no team if omitted. |
|
||||
| team_id | integer | json | The team ID this custom enrollment profile applies to, or no team if omitted. |
|
||||
| name | string | json | The filename of the uploaded custom enrollment profile. |
|
||||
| enrollment_profile | object | json | The custom enrollment profile's json, as documented in https://developer.apple.com/documentation/devicemanagement/profile. |
|
||||
|
||||
|
|
@ -4310,7 +4316,7 @@ Gets the custom MDM setup enrollment profile for a team or no team.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | integer | query | The team id for which to return the custom enrollment profile, or no team if omitted. |
|
||||
| team_id | integer | query | The team ID for which to return the custom enrollment profile, or no team if omitted. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -4344,7 +4350,7 @@ Deletes the custom MDM setup enrollment profile assigned to a team or no team.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | integer | query | The team id for which to delete the custom enrollment profile, or no team if omitted. |
|
||||
| team_id | integer | query | The team ID for which to delete the custom enrollment profile, or no team if omitted. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -4439,7 +4445,7 @@ Upload a bootstrap package that will be automatically installed during DEP setup
|
|||
| Name | Type | In | Description |
|
||||
| ------- | ------ | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| package | file | form | **Required**. The bootstrap package installer. It must be a signed `pkg` file. |
|
||||
| team_id | string | form | The team id for the package. If specified, the package will be installed to hosts that are assigned to the specified team. If not specified, the package will be installed to hosts that are not assigned to any team. |
|
||||
| team_id | string | form | The team ID for the package. If specified, the package will be installed to hosts that are assigned to the specified team. If not specified, the package will be installed to hosts that are not assigned to any team. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -4485,7 +4491,7 @@ Get information about a bootstrap package that was uploaded to Fleet.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------- | ------ | --- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| team_id | string | url | **Required** The team id for the package. Zero (0) can be specified to get information about the bootstrap package for hosts that don't belong to a team. |
|
||||
| team_id | string | url | **Required** The team ID for the package. Zero (0) can be specified to get information about the bootstrap package for hosts that don't belong to a team. |
|
||||
| for_update | boolean | query | If set to `true`, the authorization will be for a `write` action instead of a `read`. Useful for the write-only `gitops` role when requesting the bootstrap metadata to check if the package needs to be replaced. |
|
||||
|
||||
#### Example
|
||||
|
|
@ -4523,7 +4529,7 @@ Delete a team's bootstrap package.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------- | ------ | --- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| team_id | string | url | **Required** The team id for the package. Zero (0) can be specified to get information about the bootstrap package for hosts that don't belong to a team. |
|
||||
| team_id | string | url | **Required** The team ID for the package. Zero (0) can be specified to get information about the bootstrap package for hosts that don't belong to a team. |
|
||||
|
||||
|
||||
#### Example
|
||||
|
|
@ -4570,7 +4576,7 @@ _Available in Fleet Premium_
|
|||
|
||||
Get aggregate status counts of bootstrap packages delivered to DEP enrolled hosts.
|
||||
|
||||
The summary can optionally be filtered by team id.
|
||||
The summary can optionally be filtered by team ID.
|
||||
|
||||
`GET /api/v1/fleet/mdm/apple/bootstrap/summary`
|
||||
|
||||
|
|
@ -4578,7 +4584,7 @@ The summary can optionally be filtered by team id.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------------- | ------ | ----- | ------------------------------------------------------------------------- |
|
||||
| team_id | string | query | The team id to filter the summary. |
|
||||
| team_id | string | query | The team ID to filter the summary. |
|
||||
|
||||
#### Example
|
||||
|
||||
|
|
@ -5157,7 +5163,7 @@ Team policies work the same as policies, but at the team level.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------ | ------- | ---- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| id | integer | url | Required. Defines what team id to operate on |
|
||||
| id | integer | url | Required. Defines what team ID to operate on |
|
||||
| page | integer | query | Page number of the results to fetch. |
|
||||
| per_page | integer | query | Results per page. |
|
||||
#### Example
|
||||
|
|
@ -5261,7 +5267,7 @@ Team policies work the same as policies, but at the team level.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ------------------ | ------- | ---- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| team_id | integer | url | Defines what team id to operate on |
|
||||
| team_id | integer | url | Defines what team ID to operate on |
|
||||
| id | integer | path | **Required.** The policy's ID. |
|
||||
|
||||
#### Example
|
||||
|
|
@ -5304,7 +5310,7 @@ The semantics for creating a team policy are the same as for global policies, se
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| ---------- | ------- | ---- | ------------------------------------ |
|
||||
| team_id | integer | url | Defines what team id to operate on. |
|
||||
| team_id | integer | url | Defines what team ID to operate on. |
|
||||
| name | string | body | The query's name. |
|
||||
| query | string | body | The query in SQL. |
|
||||
| description | string | body | The query's description. |
|
||||
|
|
@ -5366,7 +5372,7 @@ Either `query` or `query_id` must be provided.
|
|||
|
||||
| Name | Type | In | Description |
|
||||
| -------- | ------- | ---- | ------------------------------------------------- |
|
||||
| team_id | integer | url | Defines what team id to operate on |
|
||||
| team_id | integer | url | Defines what team ID to operate on |
|
||||
| ids | list | body | **Required.** The IDs of the policies to delete. |
|
||||
|
||||
#### Example
|
||||
|
|
@ -6600,7 +6606,8 @@ Deletes the session specified by ID. When the user associated with the session n
|
|||
"epss_probability": 0.01537,
|
||||
"cisa_known_exploit": false,
|
||||
"cve_published": "2022-01-01 12:32:00",
|
||||
"cve_description": "In the GNU C Library (aka glibc or libc6) before 2.28, parse_reg_exp in posix/regcomp.c misparses alternatives, which allows attackers to cause a denial of service (assertion failure and application exit) or trigger an incorrect result by attempting a regular-expression match."
|
||||
"cve_description": "In the GNU C Library (aka glibc or libc6) before 2.28, parse_reg_exp in posix/regcomp.c misparses alternatives, which allows attackers to cause a denial of service (assertion failure and application exit) or trigger an incorrect result by attempting a regular-expression match.",
|
||||
"resolved_in_version": "2.28"
|
||||
}
|
||||
],
|
||||
"hosts_count": 1
|
||||
|
|
|
|||
|
|
@ -170,127 +170,11 @@ The following CIS benchmark checks cannot be automated and must be addressed man
|
|||
|
||||
Fleet's policies have been written against v1.12.0 of the benchmark. You can refer to the [CIS website](https://www.cisecurity.org/cis-benchmarks) for full details about this version.
|
||||
|
||||
### Checks that require a Group Policy Template
|
||||
### Checks that require a Group Policy template
|
||||
|
||||
38 items require Group Policy Template in place in order to audit them.
|
||||
Several items require Group Policy templates in place in order to audit them.
|
||||
These items are tagged with the label `CIS_group_policy_template_required` in the YAML file, and details about the required Group Policy templates can be found in each item's `resolution`.
|
||||
|
||||
```
|
||||
18.3.1 CIS - Ensure 'Apply UAC restrictions to local accounts on network logons' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\Apply UAC restrictions to local accounts on network logons'
|
||||
|
||||
18.3.2 CIS - Ensure 'Configure SMB v1 client driver' is set to 'Enabled: Disable driver (recommended)'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\Configure SMB v1 client driver'
|
||||
|
||||
18.3.3 CIS - Ensure 'Configure SMB v1 server' is set to 'Disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\Configure SMB v1 server'
|
||||
|
||||
18.3.4 CIS - Ensure 'Enable Structured Exception Handling Overwrite Protection (SEHOP)' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\Enable Structured Exception Handling Overwrite Protection (SEHOP)'
|
||||
|
||||
18.3.5 CIS - Ensure 'Limits print driver installation to Administrators' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\Limits print driver installation to Administrators'
|
||||
|
||||
18.3.6 CIS - Ensure 'NetBT NodeType configuration' is set to 'Enabled: P-node (recommended)'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\NetBT NodeType configuration'
|
||||
|
||||
18.3.7 CIS - Ensure 'WDigest Authentication' is set to 'Disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MS Security Guide\WDigest Authentication (disabling may require KB2871997)'
|
||||
|
||||
18.4.1 CIS - Ensure 'MSS: (AutoAdminLogon) Enable Automatic Logon (not recommended)' is set to 'Disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (AutoAdminLogon) Enable Automatic Logon (not recommended)'
|
||||
|
||||
18.4.2 CIS - Ensure 'MSS: (DisableIPSourceRouting IPv6) IP source routing protection level (protects against packet spoofing)' is set to 'Enabled: Highest protection, source routing is completely disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (DisableIPSourceRouting IPv6) IP source routing protection level (protects against packet spoofing)'
|
||||
|
||||
18.4.3 CIS - Ensure 'MSS: (DisableIPSourceRouting) IP source routing protection level (protects against packet spoofing)' is set to 'Enabled: Highest protection, source routing is completely disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (DisableIPSourceRouting) IP source routing protection level (protects against packet spoofing)'
|
||||
|
||||
18.4.4 CIS - Ensure 'MSS: (DisableSavePassword) Prevent the dial-up password from being saved' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS:(DisableSavePassword) Prevent the dial-up password from being saved'
|
||||
|
||||
18.4.5 CIS - Ensure 'MSS: (EnableICMPRedirect) Allow ICMP redirects to override OSPF generated routes' is set to 'Disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (EnableICMPRedirect) Allow ICMP redirects to override OSPF generated routes'
|
||||
|
||||
18.4.6 CIS - Ensure 'MSS: (KeepAliveTime) How often keep-alive packets are sent in milliseconds' is set to 'Enabled: 300,000 or 5 minutes'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (KeepAliveTime) How often keep-alive packets are sent in milliseconds'
|
||||
|
||||
18.4.7 CIS - Ensure 'MSS: (NoNameReleaseOnDemand) Allow the computer to ignore NetBIOS name release requests except from WINS servers' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (NoNameReleaseOnDemand) Allow the computer to ignore NetBIOS name release requests except from WINS servers'
|
||||
|
||||
18.4.8 CIS - Ensure 'MSS: (PerformRouterDiscovery) Allow IRDP to detect and configure Default Gateway addresses (could lead to DoS)' is set to 'Disabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (PerformRouterDiscovery) Allow IRDP to detect and configure Default Gateway addresses (could lead to DoS)'
|
||||
|
||||
18.4.9 CIS - Ensure 'MSS: (SafeDllSearchMode) Enable Safe DLL search mode (recommended)' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (SafeDllSearchMode) Enable Safe DLL search mode (recommended)'
|
||||
|
||||
18.4.10 CIS - Ensure 'MSS: (ScreenSaverGracePeriod) The time in seconds before the screen saver grace period expires (0 recommended)' is set to 'Enabled: 5 or fewer seconds'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (ScreenSaverGracePeriod) The time in seconds before the screen saver grace period expires (0 recommended)'
|
||||
|
||||
18.4.11 CIS - Ensure 'MSS: (TcpMaxDataRetransmissions IPv6) How many times unacknowledged data is retransmitted' is set to 'Enabled: 3'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS:(TcpMaxDataRetransmissions IPv6) How many times unacknowledged data is retransmitted'
|
||||
|
||||
18.4.12 CIS - Ensure 'MSS: (TcpMaxDataRetransmissions) How many times unacknowledged data is retransmitted' is set to 'Enabled: 3'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS:(TcpMaxDataRetransmissions) How many times unacknowledged data is retransmitted'
|
||||
|
||||
18.4.13 CIS - Ensure 'MSS: (WarningLevel) Percentage threshold for the security event log at which the system will generate a warning' is set to 'Enabled: 90% or less'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\MSS (Legacy)\MSS: (WarningLevel) Percentage threshold for the security event log at which the system will generate a warning'
|
||||
|
||||
18.8.21.2 CIS - Ensure 'Configure registry policy processing: Do not apply during periodic background processing' is set to 'Enabled: FALSE'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Group Policy\Configure registry policy processing'
|
||||
|
||||
18.8.22.1.1 CIS - Ensure 'Turn off access to the Store' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off access to the Store'
|
||||
|
||||
18.8.22.1.2 CIS - Ensure 'Turn off downloading of print drivers over HTTP' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off downloading of print drivers over HTTP'
|
||||
|
||||
18.8.22.1.3 CIS - Ensure 'Turn off handwriting personalization data sharing' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off handwriting personalization data sharing'
|
||||
|
||||
18.8.22.1.4 CIS - Ensure 'Turn off handwriting recognition error reporting' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off handwriting recognition error reporting'
|
||||
|
||||
18.8.22.1.5 CIS - Ensure 'Turn off Internet Connection Wizard if URL connection is referring to Microsoft.com' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Internet Connection Wizard if URL connection is referring to Microsoft.com'
|
||||
|
||||
18.8.22.1.6 CIS - Ensure 'Turn off Internet download for Web publishing and online ordering wizards' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Internet download for Web publishing and online ordering wizards'
|
||||
|
||||
18.8.22.1.7 CIS - Ensure 'Turn off printing over HTTP' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off printing over HTTP'
|
||||
|
||||
18.8.22.1.8 CIS - Ensure 'Turn off Registration if URL connection is referring to Microsoft.com' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Registration if URL connection is referring to Microsoft.com'
|
||||
|
||||
18.8.22.1.9 CIS - Ensure 'Turn off Search Companion content file updates' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Search Companion content file updates'
|
||||
|
||||
18.8.22.1.10 CIS - Ensure 'Turn off the "Order Prints" picture task' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off the "Order Prints" picture task'
|
||||
|
||||
18.8.22.1.11 CIS - Ensure 'Turn off the "Publish to Web" task for files and folders' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off the "Publish to Web" task for files and folders'
|
||||
|
||||
18.8.22.1.12 CIS - Ensure 'Turn off the Windows Messenger Customer Experience Improvement Program' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off the Windows Messenger Customer Experience Improvement Program'
|
||||
|
||||
18.8.22.1.13 CIS - Ensure 'Turn off Windows Customer Experience Improvement Program' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Windows Customer Experience Improvement Program'
|
||||
|
||||
18.8.22.1.14 CIS - Ensure 'Turn off Windows Error Reporting' is set to 'Enabled'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Internet Communication Management\Internet Communication settings\Turn off Windows Error Reporting'
|
||||
|
||||
18.8.25.1 CIS - Ensure 'Support device authentication using certificate' is set to 'Enabled: Automatic'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Kerberos\Support device authentication using certificate'
|
||||
|
||||
18.8.26.1 CIS - Ensure 'Enumeration policy for external devices incompatible with Kernel DMA Protection' is set to 'Enabled: Block All'
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Kernel DMA Protection\Enumeration policy for external devices incompatible with Kernel DMA Protection'
|
||||
|
||||
18.8.27.1 CIS - Ensure 'Disallow copying of user input methods to the system account for sign-in' is set to 'Enabled' (Automated)
|
||||
Requires this GPO in place: 'Computer Configuration\Policies\Administrative Templates\System\Locale Services\Disallow copying of user input methods to the system account for sign-in'
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ Fleet allows you to schedule queries to run at a set frequency. Scheduled querie
|
|||
|
||||
The default log destination, **filesystem**, is good to start. With this set, data is sent to the `/var/log/osquery/osqueryd.snapshots.log` file on each host’s filesystem. To see which log destinations are available in Fleet, head to the [log destinations page](https://fleetdm.com/docs/using-fleet/log-destinations).
|
||||
|
||||
By default, queries that run on a schedule will only target platforms compatible with that query. This behavior can be overridden by setting the platforms in the "advanced options" when saving a query.
|
||||
By default, queries that run on a schedule will only target platforms compatible with that query. This behavior can be overridden by setting the platforms in "advanced options" when saving a query.
|
||||
|
||||
**How to schedule queries:**
|
||||
|
||||
|
|
@ -94,4 +94,4 @@ See "[Agent configuration](https://fleetdm.com/docs/configuration/agent-configur
|
|||
<meta name="title" value="Fleet UI">
|
||||
<meta name="pageOrderInSection" value="200">
|
||||
<meta name="description" value="Learn how to create, run, and schedule queries, as well as update agent options in the Fleet user interface.">
|
||||
<meta name="navSection" value="The basics">
|
||||
<meta name="navSection" value="The basics">
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ GitOps is an API-only and write-only role that can be used on CI/CD pipelines.
|
|||
| View Apple mobile device management (MDM) certificate information | | | | ✅ | |
|
||||
| View Apple business manager (BM) information | | | | ✅ | |
|
||||
| Generate Apple mobile device management (MDM) certificate signing request (CSR) | | | | ✅ | |
|
||||
| View disk encryption key for macOS hosts | ✅ | ✅ | ✅ | ✅ | |
|
||||
| View disk encryption key for macOS and Windows hosts | ✅ | ✅ | ✅ | ✅ | |
|
||||
| Create edit and delete configuration profiles for macOS hosts | | | ✅ | ✅ | ✅ |
|
||||
| Execute MDM commands on macOS and Windows hosts*** | | | ✅ | ✅ | |
|
||||
| View results of MDM commands executed on macOS and Windows hosts*** | ✅ | ✅ | ✅ | ✅ | |
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/pkg/file"
|
||||
"github.com/fleetdm/fleet/v4/pkg/optjson"
|
||||
"github.com/fleetdm/fleet/v4/server/authz"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxdb"
|
||||
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
|
||||
|
|
@ -890,12 +891,7 @@ func (svc *Service) getOrCreatePreassignTeam(ctx context.Context, groups []strin
|
|||
}
|
||||
|
||||
payload.MDM = &fleet.TeamPayloadMDM{
|
||||
MacOSSettings: &fleet.MacOSSettings{
|
||||
// teams created by the match endpoint have disk encryption
|
||||
// enabled by default.
|
||||
// TODO: maybe make this configurable?
|
||||
EnableDiskEncryption: true,
|
||||
},
|
||||
EnableDiskEncryption: optjson.SetBool(true),
|
||||
MacOSSetup: &fleet.MacOSSetup{
|
||||
MacOSSetupAssistant: ac.MDM.MacOSSetup.MacOSSetupAssistant,
|
||||
// NOTE: BootstrapPackage is currently ignored by svc.ModifyTeam and gets set
|
||||
|
|
@ -968,3 +964,51 @@ func teamNameFromPreassignGroups(groups []string) string {
|
|||
|
||||
return strings.Join(groups, " - ")
|
||||
}
|
||||
|
||||
func (svc *Service) GetMDMDiskEncryptionSummary(ctx context.Context, teamID *uint) (*fleet.MDMDiskEncryptionSummary, error) {
|
||||
// TODO: Consider adding a new generic OSSetting type or Windows-specific type for authz checks
|
||||
// like this.
|
||||
if err := svc.authz.Authorize(ctx, fleet.MDMAppleConfigProfile{TeamID: teamID}, fleet.ActionRead); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err)
|
||||
}
|
||||
var macOS fleet.MDMAppleFileVaultSummary
|
||||
if m, err := svc.ds.GetMDMAppleFileVaultSummary(ctx, teamID); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting filevault summary")
|
||||
} else if m != nil {
|
||||
macOS = *m
|
||||
}
|
||||
|
||||
var windows fleet.MDMWindowsBitLockerSummary
|
||||
if w, err := svc.ds.GetMDMWindowsBitLockerSummary(ctx, teamID); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "getting bitlocker summary")
|
||||
} else if w != nil {
|
||||
windows = *w
|
||||
}
|
||||
|
||||
return &fleet.MDMDiskEncryptionSummary{
|
||||
Verified: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.Verified,
|
||||
Windows: windows.Verified,
|
||||
},
|
||||
Verifying: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.Verifying,
|
||||
Windows: windows.Verifying,
|
||||
},
|
||||
ActionRequired: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.ActionRequired,
|
||||
Windows: windows.ActionRequired,
|
||||
},
|
||||
Enforcing: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.Enforcing,
|
||||
Windows: windows.Enforcing,
|
||||
},
|
||||
Failed: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.Failed,
|
||||
Windows: windows.Failed,
|
||||
},
|
||||
RemovingEnforcement: fleet.MDMPlatformsCounts{
|
||||
MacOS: macOS.RemovingEnforcement,
|
||||
Windows: windows.RemovingEnforcement,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,13 +150,13 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
|||
}
|
||||
}
|
||||
|
||||
if payload.MDM.MacOSSettings != nil {
|
||||
if !appCfg.MDM.EnabledAndConfigured && payload.MDM.MacOSSettings.EnableDiskEncryption {
|
||||
if payload.MDM.EnableDiskEncryption.Valid {
|
||||
macOSDiskEncryptionUpdated = team.Config.MDM.EnableDiskEncryption != payload.MDM.EnableDiskEncryption.Value
|
||||
if macOSDiskEncryptionUpdated && !appCfg.MDM.EnabledAndConfigured {
|
||||
return nil, fleet.NewInvalidArgumentError("macos_settings.enable_disk_encryption",
|
||||
`Couldn't update macos_settings because MDM features aren't turned on in Fleet. Use fleetctl generate mdm-apple and then fleet serve with mdm configuration to turn on MDM features.`)
|
||||
}
|
||||
macOSDiskEncryptionUpdated = team.Config.MDM.MacOSSettings.EnableDiskEncryption != payload.MDM.MacOSSettings.EnableDiskEncryption
|
||||
team.Config.MDM.MacOSSettings.EnableDiskEncryption = payload.MDM.MacOSSettings.EnableDiskEncryption
|
||||
team.Config.MDM.EnableDiskEncryption = payload.MDM.EnableDiskEncryption.Value
|
||||
}
|
||||
|
||||
if payload.MDM.MacOSSetup != nil {
|
||||
|
|
@ -225,7 +225,7 @@ func (svc *Service) ModifyTeam(ctx context.Context, teamID uint, payload fleet.T
|
|||
}
|
||||
if macOSDiskEncryptionUpdated {
|
||||
var act fleet.ActivityDetails
|
||||
if team.Config.MDM.MacOSSettings.EnableDiskEncryption {
|
||||
if team.Config.MDM.EnableDiskEncryption {
|
||||
act = fleet.ActivityTypeEnabledMacosDiskEncryption{TeamID: &team.ID, TeamName: &team.Name}
|
||||
if err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, &team.ID); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "enable team filevault and escrow")
|
||||
|
|
@ -802,6 +802,17 @@ func (svc *Service) createTeamFromSpec(
|
|||
`Couldn't update macos_setup because MDM features aren't turned on in Fleet. Use fleetctl generate mdm-apple and then fleet serve with mdm configuration to turn on MDM features.`))
|
||||
}
|
||||
}
|
||||
enableDiskEncryption := spec.MDM.EnableDiskEncryption.Value
|
||||
if !spec.MDM.EnableDiskEncryption.Valid {
|
||||
if de := macOSSettings.DeprecatedEnableDiskEncryption; de != nil {
|
||||
enableDiskEncryption = *de
|
||||
}
|
||||
}
|
||||
|
||||
if enableDiskEncryption && !defaults.MDM.AtLeastOnePlatformEnabledAndConfigured() {
|
||||
return nil, ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("mdm",
|
||||
`Couldn't edit enable_disk_encryption. Neither macOS MDM nor Windows is turned on. Visit https://fleetdm.com/docs/using-fleet to learn how to turn on MDM.`))
|
||||
}
|
||||
|
||||
if dryRun {
|
||||
return &fleet.Team{Name: spec.Name}, nil
|
||||
|
|
@ -813,9 +824,10 @@ func (svc *Service) createTeamFromSpec(
|
|||
AgentOptions: agentOptions,
|
||||
Features: features,
|
||||
MDM: fleet.TeamMDM{
|
||||
MacOSUpdates: spec.MDM.MacOSUpdates,
|
||||
MacOSSettings: macOSSettings,
|
||||
MacOSSetup: macOSSetup,
|
||||
EnableDiskEncryption: enableDiskEncryption,
|
||||
MacOSUpdates: spec.MDM.MacOSUpdates,
|
||||
MacOSSettings: macOSSettings,
|
||||
MacOSSetup: macOSSetup,
|
||||
},
|
||||
},
|
||||
Secrets: secrets,
|
||||
|
|
@ -824,7 +836,7 @@ func (svc *Service) createTeamFromSpec(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if macOSSettings.EnableDiskEncryption {
|
||||
if enableDiskEncryption && defaults.MDM.EnabledAndConfigured {
|
||||
if err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, &tm.ID); err != nil {
|
||||
return nil, ctxerr.Wrap(ctx, err, "enable team filevault and escrow")
|
||||
}
|
||||
|
|
@ -871,11 +883,23 @@ func (svc *Service) editTeamFromSpec(
|
|||
team.Config.MDM.MacOSUpdates = spec.MDM.MacOSUpdates
|
||||
}
|
||||
|
||||
oldMacOSDiskEncryption := team.Config.MDM.MacOSSettings.EnableDiskEncryption
|
||||
oldMacOSDiskEncryption := team.Config.MDM.EnableDiskEncryption
|
||||
if err := svc.applyTeamMacOSSettings(ctx, spec, &team.Config.MDM.MacOSSettings); err != nil {
|
||||
return err
|
||||
}
|
||||
newMacOSDiskEncryption := team.Config.MDM.MacOSSettings.EnableDiskEncryption
|
||||
|
||||
// 1. if the spec has the new setting, use that
|
||||
// 2. else if the spec has the deprecated setting, use that
|
||||
// 3. otherwise, leave the setting untouched
|
||||
if spec.MDM.EnableDiskEncryption.Valid {
|
||||
team.Config.MDM.EnableDiskEncryption = spec.MDM.EnableDiskEncryption.Value
|
||||
} else if de := team.Config.MDM.MacOSSettings.DeprecatedEnableDiskEncryption; de != nil {
|
||||
team.Config.MDM.EnableDiskEncryption = *de
|
||||
}
|
||||
if team.Config.MDM.EnableDiskEncryption && !appCfg.MDM.AtLeastOnePlatformEnabledAndConfigured() {
|
||||
return ctxerr.Wrap(ctx, fleet.NewInvalidArgumentError("mdm",
|
||||
`Couldn't edit enable_disk_encryption. Neither macOS MDM nor Windows is turned on. Visit https://fleetdm.com/docs/using-fleet to learn how to turn on MDM.`))
|
||||
}
|
||||
|
||||
oldMacOSSetup := team.Config.MDM.MacOSSetup
|
||||
if spec.MDM.MacOSSetup.MacOSSetupAssistant.Set || spec.MDM.MacOSSetup.BootstrapPackage.Set {
|
||||
|
|
@ -925,9 +949,9 @@ func (svc *Service) editTeamFromSpec(
|
|||
return err
|
||||
}
|
||||
}
|
||||
if oldMacOSDiskEncryption != newMacOSDiskEncryption {
|
||||
if appCfg.MDM.EnabledAndConfigured && oldMacOSDiskEncryption != team.Config.MDM.EnableDiskEncryption {
|
||||
var act fleet.ActivityDetails
|
||||
if team.Config.MDM.MacOSSettings.EnableDiskEncryption {
|
||||
if team.Config.MDM.EnableDiskEncryption {
|
||||
act = fleet.ActivityTypeEnabledMacosDiskEncryption{TeamID: &team.ID, TeamName: &team.Name}
|
||||
if err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, &team.ID); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "enable team filevault and escrow")
|
||||
|
|
@ -982,7 +1006,7 @@ func (svc *Service) applyTeamMacOSSettings(ctx context.Context, spec *fleet.Team
|
|||
}
|
||||
|
||||
if (setFields["custom_settings"] && len(applyUpon.CustomSettings) > 0) ||
|
||||
(setFields["enable_disk_encryption"] && applyUpon.EnableDiskEncryption) {
|
||||
(setFields["enable_disk_encryption"] && *applyUpon.DeprecatedEnableDiskEncryption) {
|
||||
field := "custom_settings"
|
||||
if !setFields["custom_settings"] {
|
||||
field = "enable_disk_encryption"
|
||||
|
|
@ -1016,8 +1040,8 @@ func unmarshalWithGlobalDefaults(b *json.RawMessage) (fleet.Features, error) {
|
|||
func (svc *Service) updateTeamMDMAppleSettings(ctx context.Context, tm *fleet.Team, payload fleet.MDMAppleSettingsPayload) error {
|
||||
var didUpdate, didUpdateMacOSDiskEncryption bool
|
||||
if payload.EnableDiskEncryption != nil {
|
||||
if tm.Config.MDM.MacOSSettings.EnableDiskEncryption != *payload.EnableDiskEncryption {
|
||||
tm.Config.MDM.MacOSSettings.EnableDiskEncryption = *payload.EnableDiskEncryption
|
||||
if tm.Config.MDM.EnableDiskEncryption != *payload.EnableDiskEncryption {
|
||||
tm.Config.MDM.EnableDiskEncryption = *payload.EnableDiskEncryption
|
||||
didUpdate = true
|
||||
didUpdateMacOSDiskEncryption = true
|
||||
}
|
||||
|
|
@ -1029,7 +1053,7 @@ func (svc *Service) updateTeamMDMAppleSettings(ctx context.Context, tm *fleet.Te
|
|||
}
|
||||
if didUpdateMacOSDiskEncryption {
|
||||
var act fleet.ActivityDetails
|
||||
if tm.Config.MDM.MacOSSettings.EnableDiskEncryption {
|
||||
if tm.Config.MDM.EnableDiskEncryption {
|
||||
act = fleet.ActivityTypeEnabledMacosDiskEncryption{TeamID: &tm.ID, TeamName: &tm.Name}
|
||||
if err := svc.MDMAppleEnableFileVaultAndEscrow(ctx, &tm.ID); err != nil {
|
||||
return ctxerr.Wrap(ctx, err, "enable team filevault and escrow")
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const DEFAULT_CONFIG_MOCK: IConfig = {
|
|||
live_query_disabled: false,
|
||||
enable_analytics: true,
|
||||
deferred_save_host: false,
|
||||
query_reports_disabled: false,
|
||||
},
|
||||
smtp_settings: {
|
||||
enable_smtp: false,
|
||||
|
|
@ -125,6 +126,7 @@ const DEFAULT_CONFIG_MOCK: IConfig = {
|
|||
},
|
||||
fleet_desktop: { transparency_url: "https://fleetdm.com/transparency" },
|
||||
mdm: {
|
||||
enable_disk_encryption: false,
|
||||
windows_enabled_and_configured: true,
|
||||
apple_bm_default_team: "Apples",
|
||||
apple_bm_enabled_and_configured: true,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { IHost } from "interfaces/host";
|
||||
import { IHostMacMdmProfile } from "interfaces/mdm";
|
||||
import { IHostMdmProfile } from "interfaces/mdm";
|
||||
|
||||
const DEFAULT_HOST_PROFILE_MOCK: IHostMacMdmProfile = {
|
||||
const DEFAULT_HOST_PROFILE_MOCK: IHostMdmProfile = {
|
||||
profile_id: 1,
|
||||
name: "Test Profile",
|
||||
operation_type: "install",
|
||||
|
|
@ -10,8 +10,8 @@ const DEFAULT_HOST_PROFILE_MOCK: IHostMacMdmProfile = {
|
|||
};
|
||||
|
||||
export const createMockHostMacMdmProfile = (
|
||||
overrides?: Partial<IHostMacMdmProfile>
|
||||
): IHostMacMdmProfile => {
|
||||
overrides?: Partial<IHostMdmProfile>
|
||||
): IHostMdmProfile => {
|
||||
return { ...DEFAULT_HOST_PROFILE_MOCK, ...overrides };
|
||||
};
|
||||
|
||||
|
|
@ -53,6 +53,11 @@ const DEFAULT_HOST_MOCK: IHost = {
|
|||
enrollment_status: "Off",
|
||||
server_url: "https://www.example.com/1",
|
||||
profiles: [],
|
||||
os_settings: {
|
||||
disk_encryption: {
|
||||
status: null,
|
||||
},
|
||||
},
|
||||
macos_settings: {
|
||||
disk_encryption: null,
|
||||
action_required: null,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@ const DEFAULT_HOST_MDM_DATA: IHostMdmData = {
|
|||
name: "MDM Solution",
|
||||
id: 1,
|
||||
profiles: [],
|
||||
os_settings: {
|
||||
disk_encryption: {
|
||||
status: "verified",
|
||||
},
|
||||
},
|
||||
macos_settings: {
|
||||
disk_encryption: null,
|
||||
action_required: null,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const DEFAULT_QUERY_MOCK: ISchedulableQuery = {
|
|||
author_name: "Test User",
|
||||
author_email: "test@example.com",
|
||||
observer_can_run: false,
|
||||
discard_data: false,
|
||||
interval: 300,
|
||||
packs: [],
|
||||
team_id: null,
|
||||
|
|
|
|||
331
frontend/__mocks__/queryReportMock.ts
Normal file
331
frontend/__mocks__/queryReportMock.ts
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
import { IQueryReport } from "interfaces/query_report";
|
||||
|
||||
const DEFAULT_QUERY_REPORT_MOCK: IQueryReport = {
|
||||
query_id: 31,
|
||||
results: [
|
||||
{
|
||||
host_id: 1,
|
||||
host_name: "foo",
|
||||
last_fetched: "2021-01-19T17:08:31Z",
|
||||
columns: {
|
||||
model: "Razer Viper",
|
||||
vendor: "Razer",
|
||||
model_id: "0078",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 1,
|
||||
host_name: "foo",
|
||||
last_fetched: "2021-01-19T17:08:31Z",
|
||||
columns: {
|
||||
model: "USB Keyboard",
|
||||
vendor: "VIA Labs, Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB Reciever",
|
||||
vendor: "Logitech",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB Keyboard",
|
||||
vendor: "Logitech",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "YubiKey OTP+FIDO+CCID",
|
||||
vendor: "Yubico",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Lenovo USB Optical Mouse",
|
||||
vendor: "PixArt",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Lenovo Traditional USB Keyboard",
|
||||
vendor: "Lenovo",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Display Audio",
|
||||
vendor: "Bose",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB-C Digital AV Multiport Adapter",
|
||||
vendor: "Apple, Inc.",
|
||||
model_id: "1460",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB Reciever",
|
||||
vendor: "Logitech",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB-C Digital AV Multiport Adapter",
|
||||
vendor: "Apple Inc.",
|
||||
model_id: "1460",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 2,
|
||||
host_name: "bar",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "USB Reciever",
|
||||
vendor: "Logitech",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 3,
|
||||
host_name: "zoo",
|
||||
last_fetched: "2022-04-09T17:20:00Z",
|
||||
columns: {
|
||||
model: "Logitech Webcam C925e",
|
||||
model_id: "085b",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 3,
|
||||
host_name: "zoo",
|
||||
last_fetched: "2022-04-09T17:20:00Z",
|
||||
columns: {
|
||||
model: "Display Audio",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 3,
|
||||
host_name: "zoo",
|
||||
last_fetched: "2022-04-09T17:20:00Z",
|
||||
columns: {
|
||||
model: "Ambient Light Sensor",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 3,
|
||||
host_name: "zoo",
|
||||
last_fetched: "2022-04-09T17:20:00Z",
|
||||
columns: {
|
||||
model: "DELL Laser Mouse",
|
||||
model_id: "4d51",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 7,
|
||||
host_name: "Rachel's Magnificent Testing Computer of All Computers",
|
||||
last_fetched: "2023-09-21T19:03:30Z",
|
||||
columns: {
|
||||
model: "AppleUSBVHCIBCE Root Hub Simulation",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 7,
|
||||
host_name: "Rachel's Magnificent Testing Computer of All Computers",
|
||||
last_fetched: "2023-09-21T19:03:30Z",
|
||||
columns: {
|
||||
model: "QuickFire Rapid keyboard",
|
||||
vendor: "CM Storm",
|
||||
model_id: "0004",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 7,
|
||||
host_name: "Rachel's Magnificent Testing Computer of All Computers",
|
||||
last_fetched: "2023-09-21T19:03:30Z",
|
||||
columns: {
|
||||
model: "Lenovo USB Optical Mouse",
|
||||
vendor: "Lenovo",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 7,
|
||||
host_name: "Rachel's Magnificent Testing Computer of All Computers",
|
||||
last_fetched: "2023-09-21T19:03:30Z",
|
||||
columns: {
|
||||
model: "YubiKey FIDO+CCID",
|
||||
vendor: "Yubico",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 4,
|
||||
host_name: "car",
|
||||
last_fetched: "2023-01-14T12:40:30Z",
|
||||
columns: {
|
||||
model: "USB2.0 Hub",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 8,
|
||||
host_name: "apple man",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "FaceTime HD Camera (Display)",
|
||||
vendor: "Apple Inc.",
|
||||
model_id: "1112",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 8,
|
||||
host_name: "apple man",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Apple Internal Keyboard / Trackpad",
|
||||
model_id: "027e",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 8,
|
||||
host_name: "apple man",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Apple Thunderbolt Display",
|
||||
vendor: "Apple Inc.",
|
||||
model_id: "9227",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 8,
|
||||
host_name: "apple man",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "AppleUSBXHCI Root Hub Simulation",
|
||||
vendor: "Apple Inc.",
|
||||
model_id: "8007",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 8,
|
||||
host_name: "apple man",
|
||||
last_fetched: "2021-01-19T17:20:00Z",
|
||||
columns: {
|
||||
model: "Apple T2 Controller",
|
||||
vendor: "Apple Inc.",
|
||||
model_id: "8233",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 5,
|
||||
host_name: "choo",
|
||||
last_fetched: "2023-09-03T03:40:30Z",
|
||||
columns: {
|
||||
model: "4-Port USB 2.0 Hub",
|
||||
vendor: "Generic",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 5,
|
||||
host_name: "choo",
|
||||
last_fetched: "2023-09-03T03:40:30Z",
|
||||
columns: {
|
||||
model: "USB 10_100_1000 LAN",
|
||||
vendor: "Realtek",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 5,
|
||||
host_name: "choo",
|
||||
last_fetched: "2023-09-03T03:40:30Z",
|
||||
columns: {
|
||||
model: "Display Audio",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 5,
|
||||
host_name: "choo",
|
||||
last_fetched: "2023-09-03T03:40:30Z",
|
||||
columns: {
|
||||
model: "USB Mouse",
|
||||
vendor: "Razor",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 5,
|
||||
host_name: "choo",
|
||||
last_fetched: "2023-09-03T03:40:30Z",
|
||||
columns: {
|
||||
model: "USB Audio",
|
||||
vendor: "Apple, Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 6,
|
||||
host_name: "moo",
|
||||
last_fetched: "2023-09-20T07:02:34Z",
|
||||
columns: {
|
||||
model: "Display Audio",
|
||||
vendor: "Apple Inc.",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 6,
|
||||
host_name: "moo",
|
||||
last_fetched: "2023-09-20T07:02:34Z",
|
||||
columns: {
|
||||
model: "USB Reciever",
|
||||
vendor: "Logitech",
|
||||
},
|
||||
},
|
||||
{
|
||||
host_id: 6,
|
||||
host_name: "moo",
|
||||
last_fetched: "2023-09-20T07:02:34Z",
|
||||
columns: {
|
||||
model: "LG Monitor Controls",
|
||||
vendor: "LG Electronics Inc.",
|
||||
model_id: "9a39",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const createMockQueryReport = (
|
||||
overrides?: Partial<IQueryReport>
|
||||
): IQueryReport => {
|
||||
return { ...DEFAULT_QUERY_REPORT_MOCK, ...overrides };
|
||||
};
|
||||
|
||||
export default createMockQueryReport;
|
||||
|
|
@ -20,6 +20,7 @@ const DEFAULT_SCHEDULABLE_QUERY_MOCK: ISchedulableQuery = {
|
|||
author_name: "Test User",
|
||||
author_email: "test@example.com",
|
||||
observer_can_run: false,
|
||||
discard_data: false,
|
||||
packs: [],
|
||||
stats: {
|
||||
system_time_p50: 28.1053,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
&__container {
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
margin-bottom: 20px;
|
||||
min-height: 155px;
|
||||
max-width: none;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import classNames from "classnames";
|
|||
|
||||
import Icon from "components/Icon";
|
||||
import Button from "components/buttons/Button";
|
||||
import { IconNames } from "components/icons";
|
||||
|
||||
const baseClass = "info-banner";
|
||||
|
||||
|
|
@ -10,29 +11,37 @@ export interface IInfoBannerProps {
|
|||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
/** default light purple */
|
||||
color?: "yellow" | "grey";
|
||||
color?: "purple" | "purple-bold-border" | "yellow" | "grey";
|
||||
/** default 4px */
|
||||
borderRadius?: "large" | "xlarge";
|
||||
pageLevel?: boolean;
|
||||
/** cta and link are mutually exclusive */
|
||||
cta?: JSX.Element;
|
||||
/** closable and link are mutually exclusive */
|
||||
closable?: boolean;
|
||||
link?: string;
|
||||
icon?: IconNames;
|
||||
}
|
||||
|
||||
const InfoBanner = ({
|
||||
children,
|
||||
className,
|
||||
color,
|
||||
color = "purple",
|
||||
borderRadius,
|
||||
pageLevel,
|
||||
cta,
|
||||
closable,
|
||||
link,
|
||||
icon,
|
||||
}: IInfoBannerProps): JSX.Element => {
|
||||
const wrapperClasses = classNames(
|
||||
baseClass,
|
||||
`${baseClass}__${color}`,
|
||||
{
|
||||
[`${baseClass}__${color}`]: !!color,
|
||||
[`${baseClass}__border-radius-${borderRadius}`]: !!borderRadius,
|
||||
[`${baseClass}__page-banner`]: !!pageLevel,
|
||||
[`${baseClass}__icon`]: !!icon,
|
||||
},
|
||||
className
|
||||
);
|
||||
|
|
@ -42,6 +51,7 @@ const InfoBanner = ({
|
|||
const content = (
|
||||
<>
|
||||
<div className={`${baseClass}__info`}>{children}</div>
|
||||
|
||||
{(cta || closable) && (
|
||||
<div className={`${baseClass}__cta`}>
|
||||
{cta}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,19 @@
|
|||
padding: $pad-medium;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $ui-vibrant-blue-50;
|
||||
background-color: $ui-vibrant-blue-10;
|
||||
font-size: $x-small;
|
||||
font-weight: $regular;
|
||||
color: $core-fleet-black;
|
||||
|
||||
&__purple {
|
||||
background-color: $ui-vibrant-blue-10;
|
||||
}
|
||||
|
||||
&__purple-bold-border {
|
||||
background-color: $ui-vibrant-blue-10;
|
||||
border-color: $core-vibrant-blue;
|
||||
}
|
||||
|
||||
&__yellow {
|
||||
background-color: $ui-yellow-banner;
|
||||
border-color: $ui-yellow-banner-outline;
|
||||
|
|
@ -26,6 +34,20 @@
|
|||
width: auto;
|
||||
}
|
||||
|
||||
&__border-radius-large {
|
||||
border-radius: $border-radius-large;
|
||||
}
|
||||
|
||||
&__border-radius-xlarge {
|
||||
border-radius: $border-radius-xlarge;
|
||||
}
|
||||
|
||||
&__info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-small;
|
||||
}
|
||||
|
||||
&__cta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -51,4 +73,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
ISelectLabel,
|
||||
ISelectTeam,
|
||||
ISelectTargetsEntity,
|
||||
ISelectedTargets,
|
||||
ISelectedTargetsForApi,
|
||||
} from "interfaces/target";
|
||||
import { ITeam } from "interfaces/team";
|
||||
|
||||
|
|
@ -48,7 +48,9 @@ interface ISelectTargetsProps {
|
|||
targetedTeams: ITeam[];
|
||||
goToQueryEditor: () => void;
|
||||
goToRunQuery: () => void;
|
||||
setSelectedTargets: React.Dispatch<React.SetStateAction<ITarget[]>>;
|
||||
setSelectedTargets: // TODO: Refactor policy targets to streamline selectedTargets/selectedTargetsByType
|
||||
| React.Dispatch<React.SetStateAction<ITarget[]>> // Used for policies page level useState hook
|
||||
| ((value: ITarget[]) => void); // Used for queries app level QueryContext
|
||||
setTargetedHosts: React.Dispatch<React.SetStateAction<IHost[]>>;
|
||||
setTargetedLabels: React.Dispatch<React.SetStateAction<ILabel[]>>;
|
||||
setTargetedTeams: React.Dispatch<React.SetStateAction<ITeam[]>>;
|
||||
|
|
@ -65,7 +67,7 @@ interface ITargetsQueryKey {
|
|||
scope: string;
|
||||
query_id?: number | null;
|
||||
query?: string | null;
|
||||
selected?: ISelectedTargets | null;
|
||||
selected?: ISelectedTargetsForApi | null;
|
||||
}
|
||||
|
||||
const DEBOUNCE_DELAY = 500;
|
||||
|
|
@ -379,12 +381,22 @@ const SelectTargets = ({
|
|||
}
|
||||
|
||||
const { targets_count: total, targets_online: online } = counts;
|
||||
const onlinePercentage = total > 0 ? Math.round((online / total) * 100) : 0;
|
||||
const onlinePercentage = () => {
|
||||
if (total === 0) {
|
||||
return 0;
|
||||
}
|
||||
// If at least 1 host is online, displays <1% instead of 0%
|
||||
const roundPercentage =
|
||||
Math.round((online / total) * 100) === 0
|
||||
? "<1"
|
||||
: Math.round((online / total) * 100) === 0;
|
||||
return roundPercentage;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>{total}</span> host{total > 1 ? `s` : ``} targeted (
|
||||
{onlinePercentage}
|
||||
{onlinePercentage()}
|
||||
%
|
||||
<TooltipWrapper
|
||||
tipContent={`Hosts are online if they<br /> have recently checked <br />into Fleet.`}
|
||||
|
|
|
|||
|
|
@ -79,4 +79,7 @@
|
|||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.input-icon-field__icon {
|
||||
top: 34px; // Override styling to include label header
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ interface IStatusIndicatorWithIconProps {
|
|||
tooltipText: string | JSX.Element;
|
||||
position?: "top" | "bottom";
|
||||
};
|
||||
layout?: "horizontal" | "vertical";
|
||||
className?: string;
|
||||
/** Classname to add to the value text */
|
||||
valueClassName?: string;
|
||||
}
|
||||
|
||||
const statusIconNameMapping: Record<IndicatorStatus, IconNames> = {
|
||||
|
|
@ -38,13 +41,18 @@ const StatusIndicatorWithIcon = ({
|
|||
status,
|
||||
value,
|
||||
tooltip,
|
||||
layout = "horizontal",
|
||||
className,
|
||||
valueClassName,
|
||||
}: IStatusIndicatorWithIconProps) => {
|
||||
const classNames = classnames(baseClass, className);
|
||||
const id = `status-${uniqueId()}`;
|
||||
|
||||
const valueClasses = classnames(`${baseClass}__value`, valueClassName, {
|
||||
[`${baseClass}__value-vertical`]: layout === "vertical",
|
||||
});
|
||||
const valueContent = (
|
||||
<span className={`${baseClass}__value`}>
|
||||
<span className={valueClasses}>
|
||||
<Icon name={statusIconNameMapping[status]} />
|
||||
<span>{value}</span>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
.status-indicator-with-icon {
|
||||
// default layout is horizontal
|
||||
&__value {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
|
@ -8,4 +9,10 @@
|
|||
margin-right: $pad-xsmall;
|
||||
}
|
||||
}
|
||||
|
||||
// overrides for different layout
|
||||
&__value-vertical {
|
||||
flex-direction: column;
|
||||
gap: $pad-xsmall;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@ const DefaultColumnFilter = ({
|
|||
}: FilterProps<TableInstance>): JSX.Element => {
|
||||
const { setFilter } = column;
|
||||
|
||||
// Remove last_fetched filter per design as it is confusing to filter by a non-displayed date-string
|
||||
if (column.id === "last_fetched") {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={"filter-cell"}>
|
||||
<SearchField
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import * as DOMPurify from "dompurify";
|
|||
interface ITooltipWrapperProps {
|
||||
children: string | JSX.Element;
|
||||
tipContent: string;
|
||||
/** Default: bottom */
|
||||
position?: "top" | "bottom";
|
||||
isDelayed?: boolean;
|
||||
className?: string;
|
||||
|
|
|
|||
|
|
@ -341,9 +341,7 @@ $base-class: "button";
|
|||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.5;
|
||||
filter: grayscale(0.5);
|
||||
cursor: default;
|
||||
@include disabled;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import React from "react";
|
||||
import { COLORS, Colors } from "styles/var/colors";
|
||||
import { IconSizes, ICON_SIZES } from "styles/var/icon_sizes";
|
||||
|
||||
interface IChevronProps {
|
||||
color?: Colors;
|
||||
/** Default direction "down" */
|
||||
direction?: "up" | "down" | "left" | "right";
|
||||
size: IconSizes;
|
||||
}
|
||||
|
||||
const SVG_PATH = {
|
||||
|
|
@ -17,11 +19,12 @@ const SVG_PATH = {
|
|||
const Chevron = ({
|
||||
color = "core-fleet-black",
|
||||
direction = "down",
|
||||
size = "medium",
|
||||
}: IChevronProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
width={ICON_SIZES[size]}
|
||||
height={ICON_SIZES[size]}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 16 16"
|
||||
|
|
|
|||
254
frontend/components/icons/CollectingResults.tsx
Normal file
254
frontend/components/icons/CollectingResults.tsx
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
import React from "react";
|
||||
|
||||
const CollectingResults = () => {
|
||||
return (
|
||||
<svg
|
||||
width="240"
|
||||
height="126"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 240 126"
|
||||
>
|
||||
<g clipPath="url(#a)">
|
||||
<path
|
||||
d="M109.214 120.128c26.769-13.44 35.513-50.12 19.53-81.927C112.761 6.394 78.104-8.496 51.335 4.945c-26.768 13.44-35.512 50.12-19.53 81.927 15.984 31.807 50.64 46.697 77.409 33.256Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M123.697 16.088a14.505 14.505 0 0 1 10.124 4.55 14.49 14.49 0 0 1 3.94 10.374 1.478 1.478 0 0 0 2.475 1.09c.283-.26.454-.62.475-1.004a17.439 17.439 0 0 0-7.27-14.696 17.454 17.454 0 0 0-9.657-3.26 1.472 1.472 0 0 0-1.388.87 1.466 1.466 0 0 0-.034 1.127 1.475 1.475 0 0 0 1.335.95Zm22.334 16.65a1.48 1.48 0 0 0 1.055-.4 1.466 1.466 0 0 0 .463-1.03 24.47 24.47 0 0 0-.309-4.65 24.218 24.218 0 0 0-3.296-8.828 24.288 24.288 0 0 0-19.959-11.517 1.477 1.477 0 0 0-1.094 2.474c.26.283.621.454 1.005.475a21.35 21.35 0 0 1 14.901 6.693 21.332 21.332 0 0 1 5.8 15.265 1.469 1.469 0 0 0 .87 1.39c.177.08.368.123.562.128h.002Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="M185.292 85.93v6.313h-19.379v-6.314a.937.937 0 0 1 .936-.935h17.507a.935.935 0 0 1 .936.935Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M196.958 114.897V89.31a1.87 1.87 0 0 0-1.871-1.87h-65.532a1.87 1.87 0 0 0-1.871 1.87v25.587a1.87 1.87 0 0 0 1.871 1.871h65.532a1.87 1.87 0 0 0 1.871-1.871Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="M163.092 113.824v-8.418a.468.468 0 0 0-.468-.468h-3.743a.468.468 0 0 0-.468.468v8.418c0 .258.21.468.468.468h3.743c.258 0 .468-.21.468-.468Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M155.318 112.587V91.621c0-1.147-.93-2.077-2.077-2.077h-21.375c-1.147 0-2.077.93-2.077 2.077v20.966c0 1.147.93 2.076 2.077 2.076h21.375a2.076 2.076 0 0 0 2.077-2.076Z"
|
||||
fill="#E6E6F7"
|
||||
/>
|
||||
<path
|
||||
d="M181.722 112.966c6.002 0 10.867-4.863 10.867-10.862s-4.865-10.862-10.867-10.862c-6.001 0-10.866 4.863-10.866 10.862s4.865 10.862 10.866 10.862Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="M186.333 106.556v-8.907a.935.935 0 0 0-1.871 0v8.907a.936.936 0 1 0 1.871 0ZM182.59 106.556v-8.907a.935.935 0 0 0-1.871 0v8.907a.936.936 0 1 0 1.871 0ZM178.847 106.556v-8.907a.935.935 0 0 0-1.871 0v8.907a.936.936 0 1 0 1.871 0Z"
|
||||
fill="#B0B2E7"
|
||||
/>
|
||||
<path
|
||||
d="M238.012 116.625a1.578 1.578 0 0 1-.349-.035c-14.607-2.944-26.523-4.641-44.199-4.641a1.754 1.754 0 1 1 0-3.508c17.975 0 30.074 1.728 44.901 4.712a1.755 1.755 0 0 1 1.397 1.893 1.76 1.76 0 0 1-1.743 1.579h-.007Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m78.157 120.042-50.855 4.677V74.677l50.855-2.105v47.47Z"
|
||||
fill="#E6E6F7"
|
||||
/>
|
||||
<path
|
||||
d="m45.776 109.065 13.945-.905-1.448-34.76 6.882-.36 2.897 47.792-40.836 3.873 18.56-15.64Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m38.328 123-1.048-.936c.025-.011 2.793-1.218 5.418-4.842 4.405-6.08 5.708-14.145 5.455-19.877-.253-5.731-3.626-12.201-9.357-17.5-3.38-3.145-11.098-5.08-11.131-5.086-.033-.007 4.74-.286 6.248-.363 1.362.622 4.595 2.285 6.429 3.975 6.082 5.613 8.95 12.862 9.215 18.888.264 6.026-.41 14.498-5.11 20.917-1.92 2.626-3.897 4.061-5.02 4.735l-1.1.089Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 124.705c11.505 0 20.832-11.192 20.832-24.998 0-13.806-9.327-24.997-20.832-24.997S6.384 85.9 6.384 99.707s9.327 24.998 20.832 24.998Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 122.81c10.633 0 19.253-10.343 19.253-23.103 0-12.76-8.62-23.103-19.253-23.103-10.633 0-19.253 10.343-19.253 23.103 0 12.76 8.62 23.103 19.253 23.103Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 120.841c9.726 0 17.61-9.462 17.61-21.134s-7.884-21.134-17.61-21.134c-9.726 0-17.61 9.462-17.61 21.134s7.884 21.134 17.61 21.134Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 119.078c8.916 0 16.144-8.672 16.144-19.37 0-10.7-7.228-19.372-16.144-19.372-8.916 0-16.144 8.673-16.144 19.371 0 10.699 7.228 19.371 16.144 19.371Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 116.78c7.858 0 14.228-7.644 14.228-17.073s-6.37-17.073-14.228-17.073-14.228 7.644-14.228 17.073 6.37 17.073 14.228 17.073Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 101.505c.828 0 1.5-.805 1.5-1.798s-.672-1.798-1.5-1.798-1.5.805-1.5 1.798.672 1.798 1.5 1.798Z"
|
||||
fill="#B0B2E7"
|
||||
/>
|
||||
<path
|
||||
d="m45.814 123-.37-.884c.026-.012 2.793-1.218 5.416-4.843 4.407-6.08 5.032-14.208 4.779-19.947-.253-5.738-1.755-13.724-7.486-19.022-3.387-3.136-7.797-4.158-7.83-4.165-.032-.007 2.293-.091 3.802-.166a18.424 18.424 0 0 1 4.982 3.302c6.083 5.612 7.666 13.974 7.93 19.99.265 6.017-.409 14.499-5.108 20.918-1.92 2.626-3.898 4.061-5.02 4.735l-1.095.082Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m51.615 122.462-.234-.578c.021-.011 2.2-1.218 4.267-4.842 3.472-6.08 3.963-14.209 3.764-19.947-.199-5.738-1.382-13.724-5.892-19.023a14.248 14.248 0 0 0-6.17-4.165s1.807-.09 2.995-.166a14.737 14.737 0 0 1 3.928 3.302c4.786 5.612 6.038 13.974 6.246 19.991.208 6.017-.323 14.498-4.024 20.917-1.513 2.626-2.9 3.742-3.785 4.42-.416.04-1.095.091-1.095.091Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m23.005 99.707.9-.327c-5.953 0-11.68 5.144-11.68 11.102v10.289a3.491 3.491 0 0 1-3.495 3.492H0"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M25.11 99.707h.789c-5.954 0-11.568 4.834-11.568 10.785v10.289a3.486 3.486 0 0 1-2.158 3.226 3.505 3.505 0 0 1-1.337.265h-8.73"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M27.216 99.707a10.781 10.781 0 0 0-10.78 10.775v10.289a3.493 3.493 0 0 1-3.495 3.492h-8.73"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="m70.225 65.3-5.547.19-.089-20.897 5.547-.119.089 20.826Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m83.854 125.404-4.396.402a14.325 14.325 0 0 1-14.427-8.467 14.309 14.309 0 0 1-1.22-5.783V65.894a.702.702 0 0 1 .685-.702l19.358-.451v60.663Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m131.515 64.13-61.924 1.125-.09-21.363 61.923.816.091 19.423Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m82.5 56.283-5.536.072a1.997 1.997 0 0 1-2.02-1.99v-.92a1.993 1.993 0 0 1 2.006-2l5.533.033a1.996 1.996 0 0 1 1.984 1.987v.816a1.992 1.992 0 0 1-1.968 2.002Z"
|
||||
fill="#B0B2E7"
|
||||
/>
|
||||
<path
|
||||
d="m121.59 121.333-39.245 4.396a11.72 11.72 0 0 1-9.11-2.908 11.71 11.71 0 0 1-3.904-8.726V65.134l61.951-1.155a.705.705 0 0 1 .659.43.701.701 0 0 1 .054.271v45.033a11.698 11.698 0 0 1-10.405 11.62Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="m81.921 44.02-17.22.63a.701.701 0 0 1-.727-.702l-.037-10.338c-.029-7.633 6.126-13.616 13.762-13.668l4.134-.026-1.736 3.508-5.977 5.081 2.987 12.038 4.814 3.478Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="M74.09 22.229v3.04l39.38 1.183a6.519 6.519 0 0 1 6.274 6.618l-.047 2.787a5.477 5.477 0 0 1-5.528 5.378l-40.08-.194v1.085h52.883v-16.79L74.089 22.23Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m121.976 21.855-40.195-1.948a11.89 11.89 0 0 0-11.5 7.186 11.876 11.876 0 0 0-.962 4.679v12.627l61.958.468a.702.702 0 0 0 .702-.702V32.36a10.523 10.523 0 0 0-10.003-10.504Zm4.559 12.26a7.268 7.268 0 0 1-7.306 7.275l-34.856-.162a8.636 8.636 0 0 1-8.595-8.628v-1.523a6.928 6.928 0 0 1 4.455-6.472 6.938 6.938 0 0 1 2.73-.454l37.045 1.373a6.78 6.78 0 0 1 6.529 6.765l-.002 1.826Z"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="m126.441 111.109-46.035 5.685a6.245 6.245 0 0 1-4.893-1.518 6.23 6.23 0 0 1-2.102-4.67V76.117h53.03v34.992Z"
|
||||
fill="#D7DAF5"
|
||||
/>
|
||||
<path
|
||||
d="m126.182 111.074-45.325 4.859a5.788 5.788 0 0 1-5.855-3.277 5.79 5.79 0 0 1-.555-2.302l-1.03-33.327a5.844 5.844 0 0 1 5.653-6.035l46.059-1.705a4.958 4.958 0 0 1 5.147 4.786l1.052 31.115a5.712 5.712 0 0 1-5.146 5.886Z"
|
||||
fill="#fff"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="m125.992 97.92-46.454 3.821a3.59 3.59 0 0 1-2.682-.897 3.587 3.587 0 0 1-1.197-2.561l-.688-21.565a4.054 4.054 0 0 1 3.9-4.18l46.532-1.806a3.664 3.664 0 0 1 3.482 2.158c.198.442.307.919.319 1.403l.508 19.477a4.05 4.05 0 0 1-3.72 4.15Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="m126.189 96.45-46.506 3.809a2.503 2.503 0 0 1-1.881-.63 2.51 2.51 0 0 1-.838-1.797L76.42 79.11a2.68 2.68 0 0 1 2.574-2.761l46.929-1.913a2.005 2.005 0 0 1 2.091 1.964l.384 17.604a2.404 2.404 0 0 1-2.208 2.446Z"
|
||||
fill="#F1F1FD"
|
||||
/>
|
||||
<path
|
||||
d="M99.03 53.399v1.328h-3.676V53.4h3.677Zm-3.1-2.845v7.166h-1.728v-7.166h1.728Zm4.262 0v7.166H98.47v-7.166h1.722Zm6.634 5.837v1.329h-3.819v-1.329h3.819Zm-3.204-5.837v7.166h-1.727v-7.166h1.727Zm2.712 2.845v1.284h-3.327V53.4h3.327Zm.507-2.845v1.334h-3.834v-1.334h3.834Zm6.034 5.837v1.329h-3.623v-1.329h3.623Zm-3.008-5.837v7.166h-1.727v-7.166h1.727Zm9.076 5.837v1.329h-3.623v-1.329h3.623Zm-3.007-5.837v7.166h-1.728v-7.166h1.728Zm10.089 3.44v.29c0 .549-.077 1.04-.232 1.477-.15.433-.365.804-.644 1.112-.279.306-.609.54-.99.704-.38.161-.8.241-1.26.241-.462 0-.886-.08-1.269-.24a2.915 2.915 0 0 1-.995-.705 3.266 3.266 0 0 1-.649-1.112 4.499 4.499 0 0 1-.227-1.477v-.29c0-.548.076-1.04.227-1.476a3.26 3.26 0 0 1 .644-1.113c.279-.308.609-.543.99-.704a3.198 3.198 0 0 1 1.27-.246c.459 0 .879.082 1.26.246.383.161.715.396.994.704.279.305.495.676.649 1.113.155.436.232.928.232 1.476Zm-1.752.29v-.3a4.19 4.19 0 0 0-.094-.935 2.071 2.071 0 0 0-.266-.684 1.18 1.18 0 0 0-1.023-.556 1.143 1.143 0 0 0-1.029.556 2.138 2.138 0 0 0-.261.684c-.056.27-.084.58-.084.935v.3c0 .352.028.663.084.936.059.269.146.497.261.684.118.187.262.328.433.423.174.095.376.143.605.143.22 0 .415-.048.586-.143.171-.095.313-.236.428-.423.118-.187.207-.415.266-.684.062-.273.094-.584.094-.935ZM95.558 86.67a2.264 2.264 0 1 0 0-4.527 2.264 2.264 0 0 0 0 4.528ZM111.699 85.735a2.263 2.263 0 1 0 0-4.527 2.264 2.264 0 1 0 0 4.527Z"
|
||||
fill="#B0B2E7"
|
||||
/>
|
||||
<path
|
||||
d="m101.375 89.205 5.797-.234"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.887"
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M165.913 87.386v-1.457a.937.937 0 0 1 .936-.935h17.507a.935.935 0 0 1 .936.935v1.548"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M131.894 87.44h63.193a1.871 1.871 0 0 1 1.871 1.87v25.585a1.871 1.871 0 0 1-1.871 1.871h-65.338"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M131.864 89.544h21.274a2.182 2.182 0 0 1 2.18 2.18v20.753a2.178 2.178 0 0 1-2.18 2.179h-22.196M181.722 112.966c6.002 0 10.867-4.863 10.867-10.862s-4.865-10.862-10.867-10.862c-6.001 0-10.866 4.863-10.866 10.862s4.865 10.862 10.866 10.862ZM196.956 108.464c16.092.213 27.558 1.904 41.406 4.689a1.755 1.755 0 0 1 .83 3.018 1.75 1.75 0 0 1-1.524.419c-13.629-2.743-24.917-4.408-40.728-4.618M29.296 124.59l38.033-3.515M69.01 43.747a.774.774 0 0 0 .765.783l61.172.398a.98.98 0 0 0 .992-.966c0-1.87 0-6.262-.045-12.188-.03-5.144-3.534-7.716-6.012-8.902-1.201-.56-2.5-.878-3.825-.936-6.187-.299-30.998-1.508-40.795-2.06a8.657 8.657 0 0 0-1.907.103c-10.125 1.654-10.11 12.244-10.11 12.244l-.235 11.524Z"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M79.914 19.904s-11.837-.603-15.194 9.31a14.378 14.378 0 0 0-.723 4.517c-.03 4.488-.014 8.091 0 9.822a1.103 1.103 0 0 0 1.13 1.11l4.494-.095M69.736 44.654v20.33M64.844 44.654v20.419M131.26 45.16v18.737M131.894 64.816v45.531a10.753 10.753 0 0 1-9.546 10.696l-40.558 4.599a11.371 11.371 0 0 1-8.856-2.815 11.36 11.36 0 0 1-3.795-8.479v-48.55a.828.828 0 0 1 .814-.828l61.073-1.005a.849.849 0 0 1 .868.85Z"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M81.152 125.691c-10.595.875-17.393-5.96-17.393-14.03V65.999a.783.783 0 0 1 .744-.781l5.542-.264M26.035 74.721l37.55-1.328M27.216 124.704c11.505 0 20.832-11.191 20.832-24.997S38.72 74.71 27.216 74.71 6.384 85.9 6.384 99.707s9.327 24.997 20.832 24.997ZM119.606 41.357H84.191a8.169 8.169 0 0 1-8.162-8.166v-2.754a6.473 6.473 0 0 1 6.725-6.47l37.385 1.447a6.782 6.782 0 0 1 6.527 6.795v2.105a7.04 7.04 0 0 1-4.359 6.51 7.055 7.055 0 0 1-2.701.533Z"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="m78.649 25.278 34.912 1.11a6.426 6.426 0 0 1 6.227 6.428v3.195a5.352 5.352 0 0 1-5.303 5.353M163.092 113.824v-8.418a.468.468 0 0 0-.468-.468h-3.743a.468.468 0 0 0-.468.468v8.418c0 .258.21.468.468.468h3.743c.258 0 .468-.21.468-.468Z"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth=".472"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M147.107 117.091c.261 2.609-1.423 4.289-6.054 4.289M76.927 53.472v8.797a4.977 4.977 0 0 1-4.98 4.976h-7.17c-3.4 0-8.497 2.757-8.497 6.157"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M79.734 53.472v8.797a4.977 4.977 0 0 1-4.98 4.976h-7.17c-3.4 0-8.497 2.757-8.497 6.157"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="M82.307 53.472v8.797a4.977 4.977 0 0 1-4.98 4.976h-7.17c-3.4 0-8.497 2.757-8.497 6.157"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
<path
|
||||
d="m140.211 121.8-4.319-.002a9.98 9.98 0 0 1-9.984-9.98v-3.566a3.564 3.564 0 0 0-3.56-3.562h-.234"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M157.707 86.156h-.708.708Zm-7.198-7.195v.707-.707Zm-28.391 29.291-.707-.001v.001h.707Zm-3.56-4.269a.707.707 0 1 0 0 1.415v-1.415Zm39.856-16.604v-1.223h-1.415v1.223h1.415Zm0-1.223a7.903 7.903 0 0 0-2.315-5.588l-1.001 1a6.487 6.487 0 0 1 1.901 4.588h1.415Zm-2.315-5.588a7.908 7.908 0 0 0-5.59-2.315v1.415c1.721 0 3.372.684 4.589 1.9l1.001-1Zm-5.59-2.315a7.905 7.905 0 0 0-5.59 2.315l1 1a6.492 6.492 0 0 1 4.59-1.9v-1.415Zm-5.59 2.315a7.9 7.9 0 0 0-2.316 5.588h1.415c0-1.72.684-3.37 1.901-4.587l-1-1.001Zm-2.316 5.588v30.6h1.415v-30.6h-1.415Zm0 30.6a5.033 5.033 0 0 1-1.476 3.561l1.001 1.001a6.452 6.452 0 0 0 1.89-4.562h-1.415Zm-1.476 3.561a5.039 5.039 0 0 1-3.562 1.475v1.415c1.711 0 3.353-.68 4.563-1.889l-1.001-1.001Zm-3.562 1.475h-5.462v1.415h5.462v-1.415Zm-5.462 0a9.279 9.279 0 0 1-6.56-2.716l-1 1.001a10.694 10.694 0 0 0 7.56 3.13v-1.415Zm-6.56-2.716a9.27 9.27 0 0 1-2.717-6.557h-1.415c0 2.835 1.126 5.553 3.132 7.558l1-1.001Zm-2.717-6.557v-4.267h-1.415v4.267h1.415Zm0-4.267c0-.561-.11-1.116-.324-1.634l-1.308.541c.144.347.217.717.217 1.092l1.415.001Zm-.324-1.634a4.288 4.288 0 0 0-.925-1.385l-1.001 1.001c.265.265.475.579.618.925l1.308-.541Zm-.925-1.385a4.272 4.272 0 0 0-1.385-.925l-.542 1.307c.346.143.661.354.926.619l1.001-1.001Zm-1.385-.925a4.26 4.26 0 0 0-1.634-.325v1.415c.375 0 .746.074 1.092.217l.542-1.307Z"
|
||||
fill="#B0B2E7"
|
||||
/>
|
||||
<path
|
||||
d="M153.543 87.379v-1.223a7.194 7.194 0 0 0-7.199-7.195h-.329c-4.492.203-7.57 4.642-6.38 8.977l7.134 25.939c.22.798.331 1.623.331 2.45v.846"
|
||||
stroke="#B0B2E7"
|
||||
strokeWidth="1.415"
|
||||
strokeMiterlimit="10"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M0 0h240v126H0z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default CollectingResults;
|
||||
|
|
@ -4,6 +4,7 @@ import ArrowInternalLink from "./ArrowInternalLink";
|
|||
import CalendarCheck from "./CalendarCheck";
|
||||
import Check from "./Check";
|
||||
import Chevron from "./Chevron";
|
||||
import CollectingResults from "./CollectingResults";
|
||||
import Columns from "./Columns";
|
||||
import CriticalPolicy from "./CriticalPolicy";
|
||||
import Disable from "./Disable";
|
||||
|
|
@ -84,6 +85,7 @@ export const ICON_MAP = {
|
|||
"calendar-check": CalendarCheck,
|
||||
chevron: Chevron,
|
||||
check: Check,
|
||||
"collecting-results": CollectingResults,
|
||||
columns: Columns,
|
||||
"critical-policy": CriticalPolicy,
|
||||
disable: Disable,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,18 @@
|
|||
import React from "react";
|
||||
|
||||
import PhoneHome from "../../../../../assets/images/phone-home.svg";
|
||||
import EmptyTable from "components/EmptyTable/EmptyTable";
|
||||
|
||||
const baseClass = "awaiting-results";
|
||||
|
||||
const AwaitingResults = () => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<img src={PhoneHome} alt="awaiting results" />
|
||||
<span className={`${baseClass}__title`}>Phoning home...</span>
|
||||
<p className={`${baseClass}__description`}>
|
||||
There are currently no results to your query. Please wait while we talk
|
||||
to more hosts.
|
||||
</p>
|
||||
</div>
|
||||
<EmptyTable
|
||||
iconName="collecting-results"
|
||||
header="Phoning home..."
|
||||
info=" There are currently no results to your query. Please wait while we talk
|
||||
to more hosts."
|
||||
className={baseClass}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,19 +5,4 @@
|
|||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
margin-bottom: $pad-medium;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: $small;
|
||||
font-weight: $bold;
|
||||
margin-bottom: $pad-small;
|
||||
}
|
||||
|
||||
&__description {
|
||||
font-size: $x-small;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@ import { DEFAULT_QUERY } from "utilities/constants";
|
|||
import { DEFAULT_OSQUERY_TABLE, IOsQueryTable } from "interfaces/osquery_table";
|
||||
import { SelectedPlatformString } from "interfaces/platform";
|
||||
import { QueryLoggingOption } from "interfaces/schedulable_query";
|
||||
import {
|
||||
DEFAULT_TARGETS,
|
||||
DEFAULT_TARGETS_BY_TYPE,
|
||||
ISelectedTargetsByType,
|
||||
ITarget,
|
||||
} from "interfaces/target";
|
||||
|
||||
type Props = {
|
||||
children: ReactNode;
|
||||
|
|
@ -22,6 +28,9 @@ type InitialStateType = {
|
|||
lastEditedQueryPlatforms: SelectedPlatformString;
|
||||
lastEditedQueryMinOsqueryVersion: string;
|
||||
lastEditedQueryLoggingType: QueryLoggingOption;
|
||||
lastEditedQueryDiscardData: boolean;
|
||||
selectedQueryTargets: ITarget[]; // Mimicks old selectedQueryTargets still used for policies for SelectTargets.tsx and running a live query
|
||||
selectedQueryTargetsByType: ISelectedTargetsByType; // New format by type for cleaner app wide state
|
||||
setLastEditedQueryId: (value: number | null) => void;
|
||||
setLastEditedQueryName: (value: string) => void;
|
||||
setLastEditedQueryDescription: (value: string) => void;
|
||||
|
|
@ -31,7 +40,10 @@ type InitialStateType = {
|
|||
setLastEditedQueryPlatforms: (value: SelectedPlatformString) => void;
|
||||
setLastEditedQueryMinOsqueryVersion: (value: string) => void;
|
||||
setLastEditedQueryLoggingType: (value: string) => void;
|
||||
setLastEditedQueryDiscardData: (value: boolean) => void;
|
||||
setSelectedOsqueryTable: (tableName: string) => void;
|
||||
setSelectedQueryTargets: (value: ITarget[]) => void;
|
||||
setSelectedQueryTargetsByType: (value: ISelectedTargetsByType) => void;
|
||||
};
|
||||
|
||||
export type IQueryContext = InitialStateType;
|
||||
|
|
@ -48,6 +60,9 @@ const initialState = {
|
|||
lastEditedQueryPlatforms: DEFAULT_QUERY.platform,
|
||||
lastEditedQueryMinOsqueryVersion: DEFAULT_QUERY.min_osquery_version,
|
||||
lastEditedQueryLoggingType: DEFAULT_QUERY.logging,
|
||||
lastEditedQueryDiscardData: DEFAULT_QUERY.discard_data,
|
||||
selectedQueryTargets: DEFAULT_TARGETS,
|
||||
selectedQueryTargetsByType: DEFAULT_TARGETS_BY_TYPE,
|
||||
setLastEditedQueryId: () => null,
|
||||
setLastEditedQueryName: () => null,
|
||||
setLastEditedQueryDescription: () => null,
|
||||
|
|
@ -57,12 +72,17 @@ const initialState = {
|
|||
setLastEditedQueryPlatforms: () => null,
|
||||
setLastEditedQueryMinOsqueryVersion: () => null,
|
||||
setLastEditedQueryLoggingType: () => null,
|
||||
setLastEditedQueryDiscardData: () => null,
|
||||
setSelectedOsqueryTable: () => null,
|
||||
setSelectedQueryTargets: () => null,
|
||||
setSelectedQueryTargetsByType: () => null,
|
||||
};
|
||||
|
||||
const actions = {
|
||||
SET_SELECTED_OSQUERY_TABLE: "SET_SELECTED_OSQUERY_TABLE",
|
||||
SET_LAST_EDITED_QUERY_INFO: "SET_LAST_EDITED_QUERY_INFO",
|
||||
SET_SELECTED_QUERY_TARGETS: "SET_SELECTED_QUERY_TARGETS",
|
||||
SET_SELECTED_QUERY_TARGETS_BY_TYPE: "SET_SELECTED_QUERY_TARGETS_BY_TYPE",
|
||||
} as const;
|
||||
|
||||
const reducer = (state: InitialStateType, action: any) => {
|
||||
|
|
@ -113,6 +133,26 @@ const reducer = (state: InitialStateType, action: any) => {
|
|||
typeof action.lastEditedQueryLoggingType === "undefined"
|
||||
? state.lastEditedQueryLoggingType
|
||||
: action.lastEditedQueryLoggingType,
|
||||
lastEditedQueryDiscardData:
|
||||
typeof action.lastEditedQueryDiscardData === "undefined"
|
||||
? state.lastEditedQueryDiscardData
|
||||
: action.lastEditedQueryDiscardData,
|
||||
};
|
||||
case actions.SET_SELECTED_QUERY_TARGETS:
|
||||
return {
|
||||
...state,
|
||||
selectedQueryTargets:
|
||||
typeof action.selectedQueryTargets === "undefined"
|
||||
? state.selectedQueryTargets
|
||||
: action.selectedQueryTargets,
|
||||
};
|
||||
case actions.SET_SELECTED_QUERY_TARGETS_BY_TYPE:
|
||||
return {
|
||||
...state,
|
||||
selectedQueryTargetsByType:
|
||||
typeof action.selectedQueryTargetsByType === "undefined"
|
||||
? state.selectedQueryTargetsByType
|
||||
: action.selectedQueryTargetsByType,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
|
|
@ -135,6 +175,9 @@ const QueryProvider = ({ children }: Props) => {
|
|||
lastEditedQueryPlatforms: state.lastEditedQueryPlatforms,
|
||||
lastEditedQueryMinOsqueryVersion: state.lastEditedQueryMinOsqueryVersion,
|
||||
lastEditedQueryLoggingType: state.lastEditedQueryLoggingType,
|
||||
lastEditedQueryDiscardData: state.lastEditedQueryDiscardData,
|
||||
selectedQueryTargets: state.selectedQueryTargets,
|
||||
selectedQueryTargetsByType: state.selectedQueryTargetsByType,
|
||||
setLastEditedQueryId: (lastEditedQueryId: number | null) => {
|
||||
dispatch({
|
||||
type: actions.SET_LAST_EDITED_QUERY_INFO,
|
||||
|
|
@ -193,6 +236,26 @@ const QueryProvider = ({ children }: Props) => {
|
|||
lastEditedQueryLoggingType,
|
||||
});
|
||||
},
|
||||
setLastEditedQueryDiscardData: (lastEditedQueryDiscardData: boolean) => {
|
||||
dispatch({
|
||||
type: actions.SET_LAST_EDITED_QUERY_INFO,
|
||||
lastEditedQueryDiscardData,
|
||||
});
|
||||
},
|
||||
setSelectedQueryTargets: (selectedQueryTargets: ITarget[]) => {
|
||||
dispatch({
|
||||
type: actions.SET_SELECTED_QUERY_TARGETS,
|
||||
selectedQueryTargets,
|
||||
});
|
||||
},
|
||||
setSelectedQueryTargetsByType: (
|
||||
selectedQueryTargetsByType: ISelectedTargetsByType
|
||||
) => {
|
||||
dispatch({
|
||||
type: actions.SET_SELECTED_QUERY_TARGETS_BY_TYPE,
|
||||
selectedQueryTargetsByType,
|
||||
});
|
||||
},
|
||||
setSelectedOsqueryTable: (tableName: string) => {
|
||||
dispatch({ type: actions.SET_SELECTED_OSQUERY_TABLE, tableName });
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { filter, uniqueId } from "lodash";
|
|||
import { IHost } from "interfaces/host";
|
||||
import { ILabel } from "interfaces/label";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import { ISelectedTargets } from "interfaces/target";
|
||||
import { ISelectedTargetsForApi } from "interfaces/target";
|
||||
import targetsAPI from "services/entities/targets";
|
||||
|
||||
export interface ITargetsLabels {
|
||||
|
|
@ -25,7 +25,7 @@ export interface ITargetsQueryKey {
|
|||
scope: string;
|
||||
query: string;
|
||||
queryId: number | null;
|
||||
selected: ISelectedTargets;
|
||||
selected: ISelectedTargetsForApi;
|
||||
includeLabels: boolean;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,95 +1,11 @@
|
|||
/* Config interface is a flattened version of the fleet/config API response */
|
||||
|
||||
import {
|
||||
IWebhookHostStatus,
|
||||
IWebhookFailingPolicies,
|
||||
IWebhookSoftwareVulnerabilities,
|
||||
} from "interfaces/webhook";
|
||||
import PropTypes from "prop-types";
|
||||
import { IIntegrations } from "./integration";
|
||||
|
||||
export default PropTypes.shape({
|
||||
org_name: PropTypes.string,
|
||||
org_logo_url: PropTypes.string,
|
||||
contact_url: PropTypes.string,
|
||||
server_url: PropTypes.string,
|
||||
live_query_disabled: PropTypes.bool,
|
||||
enable_analytics: PropTypes.bool,
|
||||
enable_smtp: PropTypes.bool,
|
||||
configured: PropTypes.bool,
|
||||
sender_address: PropTypes.string,
|
||||
server: PropTypes.string,
|
||||
port: PropTypes.number,
|
||||
authentication_type: PropTypes.string,
|
||||
user_name: PropTypes.string,
|
||||
password: PropTypes.string,
|
||||
enable_ssl_tls: PropTypes.bool,
|
||||
authentication_method: PropTypes.string,
|
||||
domain: PropTypes.string,
|
||||
verify_sll_certs: PropTypes.bool,
|
||||
enable_start_tls: PropTypes.bool,
|
||||
entity_id: PropTypes.string,
|
||||
idp_image_url: PropTypes.string,
|
||||
metadata: PropTypes.string,
|
||||
metadata_url: PropTypes.string,
|
||||
idp_name: PropTypes.string,
|
||||
enable_sso: PropTypes.bool,
|
||||
enable_sso_idp_login: PropTypes.bool,
|
||||
enable_jit_provisioning: PropTypes.bool,
|
||||
host_expiry_enabled: PropTypes.bool,
|
||||
host_expiry_window: PropTypes.number,
|
||||
agent_options: PropTypes.string,
|
||||
tier: PropTypes.string,
|
||||
organization: PropTypes.string,
|
||||
device_count: PropTypes.number,
|
||||
expiration: PropTypes.string,
|
||||
mdm: PropTypes.shape({
|
||||
enabled_and_configured: PropTypes.bool,
|
||||
apple_bm_terms_expired: PropTypes.bool,
|
||||
apple_bm_enabled_and_configured: PropTypes.bool,
|
||||
windows_enabled_and_configured: PropTypes.bool,
|
||||
macos_updates: PropTypes.shape({
|
||||
minimum_version: PropTypes.string,
|
||||
deadline: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
note: PropTypes.string,
|
||||
// vulnerability_settings: PropTypes.any, TODO
|
||||
enable_host_status_webhook: PropTypes.bool,
|
||||
destination_url: PropTypes.string,
|
||||
host_percentage: PropTypes.number,
|
||||
days_count: PropTypes.number,
|
||||
logging: PropTypes.shape({
|
||||
debug: PropTypes.bool,
|
||||
json: PropTypes.bool,
|
||||
result: PropTypes.shape({
|
||||
plugin: PropTypes.string,
|
||||
config: PropTypes.shape({
|
||||
status_log_file: PropTypes.string,
|
||||
result_log_file: PropTypes.string,
|
||||
enable_log_rotation: PropTypes.bool,
|
||||
enable_log_compression: PropTypes.bool,
|
||||
}),
|
||||
}),
|
||||
status: PropTypes.shape({
|
||||
plugin: PropTypes.string,
|
||||
config: PropTypes.shape({
|
||||
status_log_file: PropTypes.string,
|
||||
result_log_file: PropTypes.string,
|
||||
enable_log_rotation: PropTypes.bool,
|
||||
enable_log_compression: PropTypes.bool,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
email: PropTypes.shape({
|
||||
backend: PropTypes.string,
|
||||
config: PropTypes.shape({
|
||||
region: PropTypes.string,
|
||||
source_arn: PropTypes.string,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export interface ILicense {
|
||||
tier: string;
|
||||
device_count: number;
|
||||
|
|
@ -113,6 +29,7 @@ export interface IMacOsMigrationSettings {
|
|||
}
|
||||
|
||||
export interface IMdmConfig {
|
||||
enable_disk_encryption: boolean;
|
||||
enabled_and_configured: boolean;
|
||||
apple_bm_default_team?: string;
|
||||
apple_bm_terms_expired: boolean;
|
||||
|
|
@ -196,6 +113,7 @@ export interface IConfig {
|
|||
live_query_disabled: boolean;
|
||||
enable_analytics: boolean;
|
||||
deferred_save_host: boolean;
|
||||
query_reports_disabled: boolean;
|
||||
};
|
||||
smtp_settings: {
|
||||
enable_smtp: boolean;
|
||||
|
|
@ -285,7 +203,10 @@ export interface IConfig {
|
|||
};
|
||||
};
|
||||
mdm: IMdmConfig;
|
||||
mdm_enabled?: boolean; // TODO: remove when windows MDM is released. Only used for windows MDM dev currently.
|
||||
/** This is the flag that determines if the windwos mdm feature flag is enabled.
|
||||
TODO: WINDOWS FEATURE FLAG: remove when windows MDM is released. Only used for windows MDM dev currently.
|
||||
*/
|
||||
mdm_enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface IWebhookSettings {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import hostQueryResult from "./campaign";
|
|||
import queryStatsInterface, { IQueryStats } from "./query_stats";
|
||||
import { ILicense, IDeviceGlobalConfig } from "./config";
|
||||
import {
|
||||
IHostMacMdmProfile,
|
||||
IHostMdmProfile,
|
||||
MdmEnrollmentStatus,
|
||||
BootstrapPackageStatus,
|
||||
DiskEncryptionStatus,
|
||||
} from "./mdm";
|
||||
|
||||
export default PropTypes.shape({
|
||||
|
|
@ -90,18 +91,16 @@ export interface IMunkiData {
|
|||
version: string;
|
||||
}
|
||||
|
||||
type MacDiskEncryptionState =
|
||||
| "applied"
|
||||
| "action_required"
|
||||
| "enforcing"
|
||||
| "failed"
|
||||
| "removing_enforcement"
|
||||
| null;
|
||||
|
||||
type MacDiskEncryptionActionRequired = "log_out" | "rotate_key" | null;
|
||||
|
||||
export interface IOSSettings {
|
||||
disk_encryption: {
|
||||
status: DiskEncryptionStatus | null;
|
||||
};
|
||||
}
|
||||
|
||||
interface IMdmMacOsSettings {
|
||||
disk_encryption: MacDiskEncryptionState | null;
|
||||
disk_encryption: DiskEncryptionStatus | null;
|
||||
action_required: MacDiskEncryptionActionRequired | null;
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +116,8 @@ export interface IHostMdmData {
|
|||
name?: string;
|
||||
server_url: string | null;
|
||||
id?: number;
|
||||
profiles: IHostMacMdmProfile[] | null;
|
||||
profiles: IHostMdmProfile[] | null;
|
||||
os_settings?: IOSSettings;
|
||||
macos_settings?: IMdmMacOsSettings;
|
||||
macos_setup?: IMdmMacOsSetup;
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ export interface IHost {
|
|||
osquery_version: string;
|
||||
os_version: string;
|
||||
build: string;
|
||||
platform_like: string;
|
||||
platform_like: string; // TODO: replace with more specific union type
|
||||
code_name: string;
|
||||
uptime: number;
|
||||
memory: number;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ export const MDM_ENROLLMENT_STATUS = {
|
|||
|
||||
export type MdmEnrollmentStatus = keyof typeof MDM_ENROLLMENT_STATUS;
|
||||
|
||||
export type ProfileSummaryResponse = Record<MdmProfileStatus, number>;
|
||||
|
||||
export interface IMdmStatusCardData {
|
||||
status: MdmEnrollmentStatus;
|
||||
hosts: number;
|
||||
|
|
@ -74,16 +72,15 @@ export type MdmProfileStatus = "verified" | "verifying" | "pending" | "failed";
|
|||
|
||||
export type MacMdmProfileOperationType = "remove" | "install";
|
||||
|
||||
export interface IHostMacMdmProfile {
|
||||
export interface IHostMdmProfile {
|
||||
profile_id: number;
|
||||
name: string;
|
||||
// identifier?: string; // TODO: add when API is updated to return this
|
||||
operation_type: MacMdmProfileOperationType;
|
||||
operation_type: MacMdmProfileOperationType | null;
|
||||
status: MdmProfileStatus;
|
||||
detail: string;
|
||||
}
|
||||
|
||||
export type FileVaultProfileStatus =
|
||||
export type DiskEncryptionStatus =
|
||||
| "verified"
|
||||
| "verifying"
|
||||
| "action_required"
|
||||
|
|
@ -91,9 +88,18 @@ export type FileVaultProfileStatus =
|
|||
| "failed"
|
||||
| "removing_enforcement";
|
||||
|
||||
// // TODO: update when list profiles API returns identifier
|
||||
// export const FLEET_FILEVAULT_PROFILE_IDENTIFIER =
|
||||
// "com.fleetdm.fleet.mdm.filevault";
|
||||
/** Currently windows disk enxryption status will only be one of these four
|
||||
values. In the future we may add more. */
|
||||
export type IWindowsDiskEncryptionStatus = Extract<
|
||||
DiskEncryptionStatus,
|
||||
"verified" | "verifying" | "enforcing" | "failed"
|
||||
>;
|
||||
|
||||
export const isWindowsDiskEncryptionStatus = (
|
||||
status: DiskEncryptionStatus
|
||||
): status is IWindowsDiskEncryptionStatus => {
|
||||
return !["action_required", "removing_enforcement"].includes(status);
|
||||
};
|
||||
|
||||
export const FLEET_FILEVAULT_PROFILE_DISPLAY_NAME = "Disk encryption";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { IPack } from "./pack";
|
|||
import { ISchedulableQuery } from "./schedulable_query";
|
||||
import { IScheduledQueryStats } from "./scheduled_query_stats";
|
||||
|
||||
export interface IQueryFormData {
|
||||
export interface IEditQueryFormData {
|
||||
description?: string | number | boolean | undefined;
|
||||
name?: string | number | boolean | undefined;
|
||||
query?: string | number | boolean | undefined;
|
||||
|
|
@ -35,7 +35,7 @@ export interface IQuery {
|
|||
stats?: IScheduledQueryStats;
|
||||
}
|
||||
|
||||
export interface IQueryFormFields {
|
||||
export interface IEditQueryFormFields {
|
||||
description: IFormField;
|
||||
name: IFormField;
|
||||
query: IFormField;
|
||||
|
|
|
|||
12
frontend/interfaces/query_report.ts
Normal file
12
frontend/interfaces/query_report.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export interface IQueryReportResultRow {
|
||||
host_id: number;
|
||||
host_name: string;
|
||||
last_fetched: string;
|
||||
columns: any;
|
||||
}
|
||||
|
||||
// Query report
|
||||
export interface IQueryReport {
|
||||
query_id: number;
|
||||
results: IQueryReportResultRow[];
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ export interface ISchedulableQuery {
|
|||
author_name: string;
|
||||
author_email: string;
|
||||
observer_can_run: boolean;
|
||||
discard_data: boolean;
|
||||
packs: IPack[];
|
||||
stats: ISchedulableQueryStats;
|
||||
}
|
||||
|
|
@ -62,6 +63,7 @@ export interface ICreateQueryRequestBody {
|
|||
query: string;
|
||||
description?: string;
|
||||
observer_can_run?: boolean;
|
||||
discard_data?: boolean;
|
||||
team_id?: number; // global query if ommitted
|
||||
interval?: number; // default 0 means never run
|
||||
platform?: SelectedPlatformString; // Might more accurately be called `platforms_to_query` – comma-sepparated string of platforms to query, default all platforms if ommitted
|
||||
|
|
@ -81,6 +83,7 @@ export interface IModifyQueryRequestBody
|
|||
query?: string;
|
||||
description?: string;
|
||||
observer_can_run?: boolean;
|
||||
discard_data?: boolean;
|
||||
frequency?: number;
|
||||
platform?: SelectedPlatformString;
|
||||
min_osquery_version?: string;
|
||||
|
|
@ -108,11 +111,12 @@ export interface IDeleteQueriesResponse {
|
|||
deleted: number; // number of queries deleted
|
||||
}
|
||||
|
||||
export interface IQueryFormFields {
|
||||
export interface IEditQueryFormFields {
|
||||
name: IFormField<string>;
|
||||
description: IFormField<string>;
|
||||
query: IFormField<string>;
|
||||
observer_can_run: IFormField<boolean>;
|
||||
discard_data: IFormField<boolean>;
|
||||
frequency: IFormField<number>;
|
||||
platforms: IFormField<SelectedPlatformString>;
|
||||
min_osquery_version: IFormField<string>;
|
||||
|
|
|
|||
|
|
@ -38,14 +38,29 @@ export interface ISelectTeam extends ITeam {
|
|||
|
||||
export type ISelectTargetsEntity = ISelectHost | ISelectLabel | ISelectTeam;
|
||||
|
||||
export interface ISelectedTargets {
|
||||
export interface ISelectedTargetsForApi {
|
||||
hosts: number[];
|
||||
labels: number[];
|
||||
teams: number[];
|
||||
}
|
||||
|
||||
export interface ISelectedTargetsByType {
|
||||
hosts: IHost[];
|
||||
labels: ILabel[];
|
||||
teams: ITeam[];
|
||||
}
|
||||
|
||||
export interface IPackTargets {
|
||||
host_ids: (number | string)[];
|
||||
label_ids: (number | string)[];
|
||||
team_ids: (number | string)[];
|
||||
}
|
||||
|
||||
// TODO: Also use for testing
|
||||
export const DEFAULT_TARGETS: ITarget[] = [];
|
||||
|
||||
export const DEFAULT_TARGETS_BY_TYPE: ISelectedTargetsByType = {
|
||||
hosts: [],
|
||||
labels: [],
|
||||
teams: [],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ export interface ITeam extends ITeamSummary {
|
|||
secrets?: IEnrollSecret[];
|
||||
role?: UserRole; // role value is included when the team is in the context of a user
|
||||
mdm?: {
|
||||
enable_disk_encryption: boolean;
|
||||
macos_updates: {
|
||||
minimum_version: string;
|
||||
deadline: string;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
margin-top: 20px;
|
||||
padding: $pad-xxlarge;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
border-radius: $border-radius-xlarge;
|
||||
z-index: 0;
|
||||
align-self: center;
|
||||
transform: translateY(80px);
|
||||
|
|
|
|||
|
|
@ -1,99 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import paths from "router/paths";
|
||||
import { buildQueryStringFromParams } from "utilities/url";
|
||||
import { MdmProfileStatus, ProfileSummaryResponse } from "interfaces/mdm";
|
||||
import MacSettingsIndicator from "pages/hosts/details/MacSettingsIndicator";
|
||||
|
||||
import { IconNames } from "components/icons";
|
||||
import Spinner from "components/Spinner";
|
||||
|
||||
const baseClass = "aggregate-mac-settings-indicators";
|
||||
|
||||
interface IAggregateDisplayOption {
|
||||
value: MdmProfileStatus;
|
||||
text: string;
|
||||
iconName: IconNames;
|
||||
tooltipText: string;
|
||||
}
|
||||
|
||||
const AGGREGATE_STATUS_DISPLAY_OPTIONS: IAggregateDisplayOption[] = [
|
||||
{
|
||||
value: "verified",
|
||||
text: "Verified",
|
||||
iconName: "success",
|
||||
tooltipText:
|
||||
"These hosts installed all configuration profiles. Fleet verified with osquery.",
|
||||
},
|
||||
{
|
||||
value: "verifying",
|
||||
text: "Verifying",
|
||||
iconName: "success-partial",
|
||||
tooltipText:
|
||||
"These hosts acknowledged all MDM commands to install configuration profiles. " +
|
||||
"Fleet is verifying the profiles are installed with osquery.",
|
||||
},
|
||||
{
|
||||
value: "pending",
|
||||
text: "Pending",
|
||||
iconName: "pending-partial",
|
||||
tooltipText:
|
||||
"These hosts will receive MDM commands to install configuration profiles when the hosts come online.",
|
||||
},
|
||||
{
|
||||
value: "failed",
|
||||
text: "Failed",
|
||||
iconName: "error",
|
||||
tooltipText:
|
||||
"These hosts failed to install configuration profiles. Click on a host to view error(s).",
|
||||
},
|
||||
];
|
||||
|
||||
interface AggregateMacSettingsIndicatorsProps {
|
||||
isLoading: boolean;
|
||||
teamId: number;
|
||||
aggregateProfileStatusData?: ProfileSummaryResponse;
|
||||
}
|
||||
|
||||
const AggregateMacSettingsIndicators = ({
|
||||
isLoading,
|
||||
teamId,
|
||||
aggregateProfileStatusData,
|
||||
}: AggregateMacSettingsIndicatorsProps) => {
|
||||
const indicators = AGGREGATE_STATUS_DISPLAY_OPTIONS.map((status) => {
|
||||
if (!aggregateProfileStatusData) return null;
|
||||
|
||||
const { value, text, iconName, tooltipText } = status;
|
||||
const count = aggregateProfileStatusData[value];
|
||||
|
||||
return (
|
||||
<div className="aggregate-mac-settings-indicator">
|
||||
<MacSettingsIndicator
|
||||
indicatorText={text}
|
||||
iconName={iconName}
|
||||
tooltip={{ tooltipText, position: "top" }}
|
||||
/>
|
||||
<a
|
||||
href={`${paths.MANAGE_HOSTS}?${buildQueryStringFromParams({
|
||||
team_id: teamId,
|
||||
macos_settings: value,
|
||||
})}`}
|
||||
>
|
||||
{count} hosts
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Spinner className={`${baseClass}__loading-spinner`} centered={false} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return <div className={baseClass}>{indicators}</div>;
|
||||
};
|
||||
|
||||
export default AggregateMacSettingsIndicators;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./AggregateMacSettingsIndicators";
|
||||
|
|
@ -4,12 +4,11 @@ import { useQuery } from "react-query";
|
|||
|
||||
import { AppContext } from "context/app";
|
||||
import SideNav from "pages/admin/components/SideNav";
|
||||
import { ProfileSummaryResponse } from "interfaces/mdm";
|
||||
import { API_NO_TEAM_ID, APP_CONTEXT_NO_TEAM_ID } from "interfaces/team";
|
||||
import mdmAPI from "services/entities/mdm";
|
||||
|
||||
import OS_SETTINGS_NAV_ITEMS from "./OSSettingsNavItems";
|
||||
import AggregateMacSettingsIndicators from "./AggregateMacSettingsIndicators";
|
||||
import ProfileStatusAggregate from "./ProfileStatusAggregate";
|
||||
import TurnOnMdmMessage from "../components/TurnOnMdmMessage";
|
||||
|
||||
const baseClass = "os-settings";
|
||||
|
|
@ -40,9 +39,10 @@ const OSSettings = ({
|
|||
data: aggregateProfileStatusData,
|
||||
refetch: refetchAggregateProfileStatus,
|
||||
isLoading: isLoadingAggregateProfileStatus,
|
||||
} = useQuery<ProfileSummaryResponse>(
|
||||
} = useQuery(
|
||||
["aggregateProfileStatuses", teamId],
|
||||
() => mdmAPI.getAggregateProfileStatuses(teamId),
|
||||
() =>
|
||||
mdmAPI.getAggregateProfileStatuses(teamId, config?.mdm_enabled ?? false),
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
retry: false,
|
||||
|
|
@ -50,7 +50,10 @@ const OSSettings = ({
|
|||
);
|
||||
|
||||
// MDM is not on so show messaging for user to enable it.
|
||||
if (!config?.mdm.enabled_and_configured) {
|
||||
if (
|
||||
!config?.mdm.enabled_and_configured &&
|
||||
!config?.mdm.windows_enabled_and_configured
|
||||
) {
|
||||
return <TurnOnMdmMessage router={router} />;
|
||||
}
|
||||
|
||||
|
|
@ -67,7 +70,7 @@ const OSSettings = ({
|
|||
<p className={`${baseClass}__description`}>
|
||||
Remotely enforce settings on macOS hosts assigned to this team.
|
||||
</p>
|
||||
<AggregateMacSettingsIndicators
|
||||
<ProfileStatusAggregate
|
||||
isLoading={isLoadingAggregateProfileStatus}
|
||||
teamId={teamId}
|
||||
aggregateProfileStatusData={aggregateProfileStatusData}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
import React from "react";
|
||||
|
||||
import paths from "router/paths";
|
||||
import { buildQueryStringFromParams } from "utilities/url";
|
||||
import { MdmProfileStatus } from "interfaces/mdm";
|
||||
import { ProfileStatusSummaryResponse } from "services/entities/mdm";
|
||||
|
||||
import Spinner from "components/Spinner";
|
||||
import StatusIndicatorWithIcon, {
|
||||
IndicatorStatus,
|
||||
} from "components/StatusIndicatorWithIcon/StatusIndicatorWithIcon";
|
||||
|
||||
import AGGREGATE_STATUS_DISPLAY_OPTIONS from "./ProfileStatusAggregateOptions";
|
||||
|
||||
const baseClass = "profile-status-aggregate";
|
||||
|
||||
interface IProfileStatusCountProps {
|
||||
statusIcon: IndicatorStatus;
|
||||
statusValue: MdmProfileStatus;
|
||||
title: string;
|
||||
teamId: number;
|
||||
hostCount: number;
|
||||
tooltipText: string;
|
||||
}
|
||||
|
||||
const ProfileStatusCount = ({
|
||||
statusIcon,
|
||||
statusValue,
|
||||
teamId,
|
||||
title,
|
||||
hostCount,
|
||||
tooltipText,
|
||||
}: IProfileStatusCountProps) => {
|
||||
const generateFilterHostsByStatusLink = () => {
|
||||
return `${paths.MANAGE_HOSTS}?${buildQueryStringFromParams({
|
||||
team_id: teamId,
|
||||
macos_settings: statusValue,
|
||||
})}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`${baseClass}__profile-status-count`}>
|
||||
<StatusIndicatorWithIcon
|
||||
status={statusIcon}
|
||||
value={title}
|
||||
tooltip={{ tooltipText, position: "top" }}
|
||||
layout="vertical"
|
||||
valueClassName={`${baseClass}__status-indicator-value`}
|
||||
/>
|
||||
<a href={generateFilterHostsByStatusLink()}>{hostCount} hosts</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface ProfileStatusAggregateProps {
|
||||
isLoading: boolean;
|
||||
teamId: number;
|
||||
aggregateProfileStatusData?: ProfileStatusSummaryResponse;
|
||||
}
|
||||
|
||||
const ProfileStatusAggregate = ({
|
||||
isLoading,
|
||||
teamId,
|
||||
aggregateProfileStatusData,
|
||||
}: ProfileStatusAggregateProps) => {
|
||||
if (!aggregateProfileStatusData) return null;
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Spinner className={`${baseClass}__loading-spinner`} centered={false} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const indicators = AGGREGATE_STATUS_DISPLAY_OPTIONS.map((status) => {
|
||||
const { value, text, iconName, tooltipText } = status;
|
||||
const count = aggregateProfileStatusData[value];
|
||||
|
||||
return (
|
||||
<ProfileStatusCount
|
||||
statusIcon={iconName}
|
||||
statusValue={value}
|
||||
teamId={teamId}
|
||||
title={text}
|
||||
hostCount={count}
|
||||
tooltipText={tooltipText}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return <div className={baseClass}>{indicators}</div>;
|
||||
};
|
||||
|
||||
export default ProfileStatusAggregate;
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import { MdmProfileStatus } from "interfaces/mdm";
|
||||
import { IndicatorStatus } from "components/StatusIndicatorWithIcon/StatusIndicatorWithIcon";
|
||||
|
||||
interface IAggregateDisplayOption {
|
||||
value: MdmProfileStatus;
|
||||
text: string;
|
||||
iconName: IndicatorStatus;
|
||||
tooltipText: string;
|
||||
}
|
||||
|
||||
const AGGREGATE_STATUS_DISPLAY_OPTIONS: IAggregateDisplayOption[] = [
|
||||
{
|
||||
value: "verified",
|
||||
text: "Verified",
|
||||
iconName: "success",
|
||||
tooltipText:
|
||||
"These hosts applied all OS settings. Fleet verified with osquery.",
|
||||
},
|
||||
{
|
||||
value: "verifying",
|
||||
text: "Verifying",
|
||||
iconName: "successPartial",
|
||||
tooltipText:
|
||||
"These hosts acknowledged all MDM commands to apply OS settings. " +
|
||||
"Fleet is verifying the OS settings are applied with osquery.",
|
||||
},
|
||||
{
|
||||
value: "pending",
|
||||
text: "Pending",
|
||||
iconName: "pendingPartial",
|
||||
tooltipText:
|
||||
"These hosts will receive MDM command to apply OS settings when the host come online.",
|
||||
},
|
||||
{
|
||||
value: "failed",
|
||||
text: "Failed",
|
||||
iconName: "error",
|
||||
tooltipText:
|
||||
"These host failed to apply the latest OS settings. Click on a host to view error(s).",
|
||||
},
|
||||
];
|
||||
|
||||
export default AGGREGATE_STATUS_DISPLAY_OPTIONS;
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
.aggregate-mac-settings-indicators {
|
||||
.profile-status-aggregate {
|
||||
display: flex;
|
||||
height: 94px;
|
||||
border-top: 1px solid #e2e4ea;
|
||||
border-bottom: 1px solid #e2e4ea;
|
||||
border-left: 1px solid #e2e4ea;
|
||||
border-radius: 6px;
|
||||
border-radius: $border-radius-large;
|
||||
|
||||
&__loading-spinner {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.aggregate-mac-settings-indicator {
|
||||
&__profile-status-count {
|
||||
flex-grow: 1;
|
||||
|
||||
display: flex;
|
||||
|
|
@ -29,13 +29,17 @@
|
|||
font-weight: $regular;
|
||||
}
|
||||
|
||||
.settings-indicator {
|
||||
.profile-status-indicator {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.aggregate-mac-settings-indicator:last-child {
|
||||
&__profile-status-count:last-child {
|
||||
border-top-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
}
|
||||
|
||||
&__status-indicator-value {
|
||||
font-weight: $bold;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./ProfileStatusAggregate";
|
||||
|
|
@ -31,7 +31,7 @@ const DiskEncryption = ({
|
|||
|
||||
const defaultShowDiskEncryption = currentTeamId
|
||||
? false
|
||||
: config?.mdm.macos_settings.enable_disk_encryption ?? false;
|
||||
: config?.mdm.enable_disk_encryption ?? false;
|
||||
|
||||
const [isLoadingTeam, setIsLoadingTeam] = useState(true);
|
||||
|
||||
|
|
@ -67,8 +67,7 @@ const DiskEncryption = ({
|
|||
enabled: currentTeamId !== 0,
|
||||
select: (res) => res.team,
|
||||
onSuccess: (res) => {
|
||||
const enableDiskEncryption =
|
||||
res.mdm?.macos_settings.enable_disk_encryption ?? false;
|
||||
const enableDiskEncryption = res.mdm?.enable_disk_encryption ?? false;
|
||||
setDiskEncryptionEnabled(enableDiskEncryption);
|
||||
setShowAggregate(enableDiskEncryption);
|
||||
setIsLoadingTeam(false);
|
||||
|
|
@ -100,6 +99,19 @@ const DiskEncryption = ({
|
|||
setIsLoadingTeam(false);
|
||||
}
|
||||
|
||||
const createDescriptionText = () => {
|
||||
// table is showing disk encryption status.
|
||||
if (showAggregate) {
|
||||
return "If turned on, hosts' disk encryption keys will be stored in Fleet. ";
|
||||
}
|
||||
|
||||
const isWindowsFeatureFlagEnabled = config?.mdm_enabled ?? false;
|
||||
const dynamicText = isWindowsFeatureFlagEnabled
|
||||
? " and “BitLocker” on Windows"
|
||||
: "";
|
||||
return `Also known as “FileVault” on macOS${dynamicText}. If turned on, hosts' disk encryption keys will be stored in Fleet. `;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<h2>Disk encryption</h2>
|
||||
|
|
@ -124,8 +136,7 @@ const DiskEncryption = ({
|
|||
On
|
||||
</Checkbox>
|
||||
<p>
|
||||
Apple calls this “FileVault.” If turned on, hosts' disk
|
||||
encryption keys will be stored in Fleet.{" "}
|
||||
{createDescriptionText()}
|
||||
<CustomLink
|
||||
text="Learn more"
|
||||
url="https://fleetdm.com/docs/using-fleet/mdm-disk-encryption"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
h2 {
|
||||
margin-top: 0;
|
||||
padding-bottom: $pad-small;
|
||||
margin-bottom: $pad-xxlarge;
|
||||
font-size: $medium;
|
||||
font-weight: $regular;
|
||||
color: $core-fleet-black;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import React from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
|
||||
import mdmAPI, { IFileVaultSummaryResponse } from "services/entities/mdm";
|
||||
import { AppContext } from "context/app";
|
||||
import mdmAPI, { IDiskEncryptionSummaryResponse } from "services/entities/mdm";
|
||||
|
||||
import TableContainer from "components/TableContainer";
|
||||
import EmptyTable from "components/EmptyTable";
|
||||
|
|
@ -18,25 +19,30 @@ interface IDiskEncryptionTableProps {
|
|||
currentTeamId?: number;
|
||||
}
|
||||
|
||||
const DEFAULT_SORT_HEADER = "hosts";
|
||||
const DEFAULT_SORT_DIRECTION = "asc";
|
||||
|
||||
const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
|
||||
const { config } = useContext(AppContext);
|
||||
|
||||
const {
|
||||
data: diskEncryptionStatusData,
|
||||
error: diskEncryptionStatusError,
|
||||
} = useQuery<IFileVaultSummaryResponse, Error, IFileVaultSummaryResponse>(
|
||||
} = useQuery<IDiskEncryptionSummaryResponse, Error>(
|
||||
["disk-encryption-summary", currentTeamId],
|
||||
() => mdmAPI.getDiskEncryptionAggregate(currentTeamId),
|
||||
() => mdmAPI.getDiskEncryptionSummary(currentTeamId),
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
retry: false,
|
||||
}
|
||||
);
|
||||
|
||||
const tableHeaders = generateTableHeaders();
|
||||
|
||||
const tableData = generateTableData(diskEncryptionStatusData, currentTeamId);
|
||||
// TODO: WINDOWS FEATURE FLAG: remove this when windows feature flag is removed.
|
||||
// this is used to conditianlly show "View all hosts" link in table cells.
|
||||
const windowsFeatureFlagEnabled = config?.mdm_enabled ?? false;
|
||||
const tableHeaders = generateTableHeaders(windowsFeatureFlagEnabled);
|
||||
const tableData = generateTableData(
|
||||
windowsFeatureFlagEnabled,
|
||||
diskEncryptionStatusData,
|
||||
currentTeamId
|
||||
);
|
||||
|
||||
if (diskEncryptionStatusError) {
|
||||
return <DataError />;
|
||||
|
|
@ -53,8 +59,7 @@ const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
|
|||
isLoading={false}
|
||||
showMarkAllPages={false}
|
||||
isAllPagesSelected={false}
|
||||
defaultSortHeader={DEFAULT_SORT_HEADER}
|
||||
defaultSortDirection={DEFAULT_SORT_DIRECTION}
|
||||
manualSortBy
|
||||
disableTableHeader
|
||||
disablePagination
|
||||
disableCount
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import React from "react";
|
||||
|
||||
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||
import { IFileVaultSummaryResponse } from "services/entities/mdm";
|
||||
import { DiskEncryptionStatus } from "interfaces/mdm";
|
||||
import {
|
||||
IDiskEncryptionStatusAggregate,
|
||||
IDiskEncryptionSummaryResponse,
|
||||
} from "services/entities/mdm";
|
||||
import { DISK_ENCRYPTION_QUERY_PARAM_NAME } from "services/entities/hosts";
|
||||
|
||||
import TextCell from "components/TableContainer/DataTable/TextCell";
|
||||
import HeaderCell from "components/TableContainer/DataTable/HeaderCell";
|
||||
|
|
@ -12,7 +16,7 @@ import { IndicatorStatus } from "components/StatusIndicatorWithIcon/StatusIndica
|
|||
interface IStatusCellValue {
|
||||
displayName: string;
|
||||
statusName: IndicatorStatus;
|
||||
value: FileVaultProfileStatus;
|
||||
value: DiskEncryptionStatus;
|
||||
tooltip?: string | JSX.Element;
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +32,7 @@ interface ICellProps {
|
|||
};
|
||||
row: {
|
||||
original: {
|
||||
includeWindows: boolean;
|
||||
status: IStatusCellValue;
|
||||
teamId: number;
|
||||
};
|
||||
|
|
@ -72,15 +77,53 @@ const defaultTableHeaders: IDataColumn[] = [
|
|||
},
|
||||
},
|
||||
{
|
||||
title: "Hosts",
|
||||
title: "macOS hosts",
|
||||
Header: (cellProps: IHeaderProps) => (
|
||||
<HeaderCell
|
||||
value={cellProps.column.title}
|
||||
isSortedDesc={cellProps.column.isSortedDesc}
|
||||
disableSortBy={false}
|
||||
disableSortBy
|
||||
/>
|
||||
),
|
||||
accessor: "hosts",
|
||||
disableSortBy: true,
|
||||
accessor: "macosHosts",
|
||||
Cell: ({
|
||||
cell: { value: aggregateCount },
|
||||
row: { original },
|
||||
}: ICellProps) => {
|
||||
return (
|
||||
<div className="disk-encryption-table__aggregate-table-data">
|
||||
<TextCell value={aggregateCount} formatter={(val) => <>{val}</>} />
|
||||
{/* TODO: WINDOWS FEATURE FLAG: remove this conditional when windows mdm
|
||||
is released. the view all UI will show in the windows column when we
|
||||
release the feature. */}
|
||||
{!original.includeWindows && (
|
||||
<ViewAllHostsLink
|
||||
className="view-hosts-link"
|
||||
queryParams={{
|
||||
[DISK_ENCRYPTION_QUERY_PARAM_NAME]: original.status.value,
|
||||
team_id: original.teamId,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const windowsTableHeader: IDataColumn[] = [
|
||||
{
|
||||
title: "Windows hosts",
|
||||
Header: (cellProps: IHeaderProps) => (
|
||||
<HeaderCell
|
||||
value={cellProps.column.title}
|
||||
isSortedDesc={cellProps.column.isSortedDesc}
|
||||
disableSortBy
|
||||
/>
|
||||
),
|
||||
disableSortBy: true,
|
||||
accessor: "windowsHosts",
|
||||
Cell: ({
|
||||
cell: { value: aggregateCount },
|
||||
row: { original },
|
||||
|
|
@ -91,7 +134,7 @@ const defaultTableHeaders: IDataColumn[] = [
|
|||
<ViewAllHostsLink
|
||||
className="view-hosts-link"
|
||||
queryParams={{
|
||||
macos_settings_disk_encryption: original.status.value,
|
||||
[DISK_ENCRYPTION_QUERY_PARAM_NAME]: original.status.value,
|
||||
team_id: original.teamId,
|
||||
}}
|
||||
/>
|
||||
|
|
@ -101,15 +144,17 @@ const defaultTableHeaders: IDataColumn[] = [
|
|||
},
|
||||
];
|
||||
|
||||
type StatusNames = keyof IFileVaultSummaryResponse;
|
||||
|
||||
type StatusEntry = [StatusNames, number];
|
||||
|
||||
export const generateTableHeaders = (): IDataColumn[] => {
|
||||
// TODO: WINDOWS FEATURE FLAG: return all headers when windows feature flag is removed.
|
||||
export const generateTableHeaders = (
|
||||
includeWindows: boolean
|
||||
): IDataColumn[] => {
|
||||
return includeWindows
|
||||
? [...defaultTableHeaders, ...windowsTableHeader]
|
||||
: defaultTableHeaders;
|
||||
return defaultTableHeaders;
|
||||
};
|
||||
|
||||
const STATUS_CELL_VALUES: Record<FileVaultProfileStatus, IStatusCellValue> = {
|
||||
const STATUS_CELL_VALUES: Record<DiskEncryptionStatus, IStatusCellValue> = {
|
||||
verified: {
|
||||
displayName: "Verified",
|
||||
statusName: "success",
|
||||
|
|
@ -122,8 +167,8 @@ const STATUS_CELL_VALUES: Record<FileVaultProfileStatus, IStatusCellValue> = {
|
|||
statusName: "successPartial",
|
||||
value: "verifying",
|
||||
tooltip:
|
||||
"These hosts acknowledged the MDM command to install disk encryption profile. " +
|
||||
"Fleet is verifying with osquery and retrieving the disk encryption key. This may take up to one hour.",
|
||||
"These hosts acknowledged the MDM command to turn on disk encryption. Fleet is verifying with " +
|
||||
"osquery and retrieving the disk encryption key. This may take up to one hour.",
|
||||
},
|
||||
action_required: {
|
||||
displayName: "Action required (pending)",
|
||||
|
|
@ -141,7 +186,7 @@ const STATUS_CELL_VALUES: Record<FileVaultProfileStatus, IStatusCellValue> = {
|
|||
statusName: "pendingPartial",
|
||||
value: "enforcing",
|
||||
tooltip:
|
||||
"These hosts will receive the MDM command to install the disk encryption profile when the hosts come online.",
|
||||
"These hosts will receive the MDM command to turn on disk encryption when the hosts come online.",
|
||||
},
|
||||
failed: {
|
||||
displayName: "Failed",
|
||||
|
|
@ -153,21 +198,41 @@ const STATUS_CELL_VALUES: Record<FileVaultProfileStatus, IStatusCellValue> = {
|
|||
statusName: "pendingPartial",
|
||||
value: "removing_enforcement",
|
||||
tooltip:
|
||||
"These hosts will receive the MDM command to remove the disk encryption profile when the hosts come online.",
|
||||
"These hosts will receive the MDM command to turn off disk encryption when the hosts come online.",
|
||||
},
|
||||
};
|
||||
|
||||
type StatusEntry = [DiskEncryptionStatus, IDiskEncryptionStatusAggregate];
|
||||
|
||||
// Order of the status column. We want the order to always be the same.
|
||||
const STATUS_ORDER = [
|
||||
"verified",
|
||||
"verifying",
|
||||
"failed",
|
||||
"action_required",
|
||||
"enforcing",
|
||||
"removing_enforcement",
|
||||
] as const;
|
||||
|
||||
export const generateTableData = (
|
||||
data?: IFileVaultSummaryResponse,
|
||||
// TODO: WINDOWS FEATURE FLAG: remove includeWindows when windows feature flag is removed.
|
||||
// This is used to conditionally show "View all hosts" link in table cells.
|
||||
includeWindows: boolean,
|
||||
data?: IDiskEncryptionSummaryResponse,
|
||||
currentTeamId?: number
|
||||
) => {
|
||||
if (!data) return [];
|
||||
const entries = Object.entries(data) as StatusEntry[];
|
||||
|
||||
return entries.map(([status, numHosts]) => ({
|
||||
// eslint-disable-next-line object-shorthand
|
||||
const rowFromStatusEntry = (
|
||||
status: DiskEncryptionStatus,
|
||||
statusAggregate: IDiskEncryptionStatusAggregate
|
||||
) => ({
|
||||
includeWindows,
|
||||
status: STATUS_CELL_VALUES[status],
|
||||
hosts: numHosts,
|
||||
macosHosts: statusAggregate.macos,
|
||||
windowsHosts: statusAggregate.windows,
|
||||
teamId: currentTeamId,
|
||||
}));
|
||||
});
|
||||
|
||||
return STATUS_ORDER.map((status) => rowFromStatusEntry(status, data[status]));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
.disk-encryption-table {
|
||||
padding: $pad-xxlarge;
|
||||
border: 1px solid $ui-fleet-black-10;
|
||||
border-radius: $border-radius;
|
||||
margin-bottom: $pad-xxlarge;
|
||||
|
||||
.data-table-block .data-table tbody td .w250 {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const TurnOnMdmMessage = ({ router }: ITurnOnMdmMessageProps) => {
|
|||
|
||||
return (
|
||||
<EmptyTable
|
||||
header="Manage your macOS hosts"
|
||||
header="Manage your hosts"
|
||||
info={"Turn on MDM to change settings on your hosts."}
|
||||
primaryButton={renderConnectButton()}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const Advanced = ({
|
|||
handleSubmit,
|
||||
isUpdatingSettings,
|
||||
}: IAppConfigFormProps): JSX.Element => {
|
||||
const [formData, setFormData] = useState<any>({
|
||||
const [formData, setFormData] = useState({
|
||||
domain: appConfig.smtp_settings.domain || "",
|
||||
verifySSLCerts: appConfig.smtp_settings.verify_ssl_certs || false,
|
||||
enableStartTLS: appConfig.smtp_settings.enable_start_tls,
|
||||
|
|
@ -26,6 +26,8 @@ const Advanced = ({
|
|||
appConfig.host_expiry_settings.host_expiry_enabled || false,
|
||||
hostExpiryWindow: appConfig.host_expiry_settings.host_expiry_window || 0,
|
||||
disableLiveQuery: appConfig.server_settings.live_query_disabled || false,
|
||||
disableQueryReports:
|
||||
appConfig.server_settings.query_reports_disabled || false,
|
||||
});
|
||||
|
||||
const {
|
||||
|
|
@ -35,6 +37,7 @@ const Advanced = ({
|
|||
enableHostExpiry,
|
||||
hostExpiryWindow,
|
||||
disableLiveQuery,
|
||||
disableQueryReports,
|
||||
} = formData;
|
||||
|
||||
const [formErrors, setFormErrors] = useState<IAppConfigFormErrors>({});
|
||||
|
|
@ -69,6 +72,7 @@ const Advanced = ({
|
|||
server_url: appConfig.server_settings.server_url || "",
|
||||
live_query_disabled: disableLiveQuery,
|
||||
enable_analytics: appConfig.server_settings.enable_analytics,
|
||||
query_reports_disabled: disableQueryReports,
|
||||
},
|
||||
smtp_settings: {
|
||||
enable_smtp: appConfig.smtp_settings.enable_smtp || false,
|
||||
|
|
@ -172,6 +176,24 @@ const Advanced = ({
|
|||
>
|
||||
Disable live queries
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
onChange={handleInputChange}
|
||||
name="disableQueryReports"
|
||||
value={disableQueryReports}
|
||||
parseTarget
|
||||
// TODO - update to JSX once tooltip wrapper refactor is merged
|
||||
// TODO - once refactor is merged, have this and bove tooltips disappear more
|
||||
// quickly to get out of users' way
|
||||
tooltip={
|
||||
'<p>Disabling query reports will decrease database usage, <br />\
|
||||
but will prevent you from accessing query results in<br /> \
|
||||
Fleet and will delete existing reports. This can also be<br />\
|
||||
disabled on a per-query basis by enabling "Discard <br />\
|
||||
data". <em>(Default: <b>Off</b>)</em></p>'
|
||||
}
|
||||
>
|
||||
Disable query reports
|
||||
</Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
import Icon from "components/Icon";
|
||||
import { DISK_ENCRYPTION_QUERY_PARAM_NAME } from "services/entities/hosts";
|
||||
|
||||
export const MANAGE_HOSTS_PAGE_FILTER_KEYS = [
|
||||
"query",
|
||||
|
|
@ -17,7 +18,7 @@ export const MANAGE_HOSTS_PAGE_FILTER_KEYS = [
|
|||
"os_version",
|
||||
"munki_issue_id",
|
||||
"low_disk_space",
|
||||
"macos_settings_disk_encryption",
|
||||
DISK_ENCRYPTION_QUERY_PARAM_NAME,
|
||||
"bootstrap_package",
|
||||
] as const;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import labelsAPI, { ILabelsResponse } from "services/entities/labels";
|
|||
import teamsAPI, { ILoadTeamsResponse } from "services/entities/teams";
|
||||
import globalPoliciesAPI from "services/entities/global_policies";
|
||||
import hostsAPI, {
|
||||
DISK_ENCRYPTION_QUERY_PARAM_NAME,
|
||||
ILoadHostsQueryKey,
|
||||
ILoadHostsResponse,
|
||||
ISortOption,
|
||||
|
|
@ -49,7 +50,7 @@ import { IOperatingSystemVersion } from "interfaces/operating_system";
|
|||
import { IPolicy, IStoredPolicyResponse } from "interfaces/policy";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import { IEmptyTableProps } from "interfaces/empty_table";
|
||||
import { FileVaultProfileStatus, BootstrapPackageStatus } from "interfaces/mdm";
|
||||
import { DiskEncryptionStatus, BootstrapPackageStatus } from "interfaces/mdm";
|
||||
|
||||
import sortUtils from "utilities/sort";
|
||||
import {
|
||||
|
|
@ -232,8 +233,8 @@ const ManageHostsPage = ({
|
|||
? parseInt(queryParams.low_disk_space, 10)
|
||||
: undefined;
|
||||
const missingHosts = queryParams?.status === "missing";
|
||||
const diskEncryptionStatus: FileVaultProfileStatus | undefined =
|
||||
queryParams?.macos_settings_disk_encryption;
|
||||
const diskEncryptionStatus: DiskEncryptionStatus | undefined =
|
||||
queryParams?.[DISK_ENCRYPTION_QUERY_PARAM_NAME];
|
||||
const bootstrapPackageStatus: BootstrapPackageStatus | undefined =
|
||||
queryParams?.bootstrap_package;
|
||||
|
||||
|
|
@ -558,7 +559,7 @@ const ManageHostsPage = ({
|
|||
};
|
||||
|
||||
const handleChangeDiskEncryptionStatusFilter = (
|
||||
newStatus: FileVaultProfileStatus
|
||||
newStatus: DiskEncryptionStatus
|
||||
) => {
|
||||
handleResetPageIndex();
|
||||
|
||||
|
|
@ -569,7 +570,7 @@ const ManageHostsPage = ({
|
|||
routeParams,
|
||||
queryParams: {
|
||||
...queryParams,
|
||||
macos_settings_disk_encryption: newStatus,
|
||||
[DISK_ENCRYPTION_QUERY_PARAM_NAME]: newStatus,
|
||||
page: 0, // resets page index
|
||||
},
|
||||
})
|
||||
|
|
@ -768,7 +769,7 @@ const ManageHostsPage = ({
|
|||
newQueryParams.os_version = osVersion;
|
||||
} else if (diskEncryptionStatus && isPremiumTier) {
|
||||
// Premium feature only
|
||||
newQueryParams.macos_settings_disk_encryption = diskEncryptionStatus;
|
||||
newQueryParams[DISK_ENCRYPTION_QUERY_PARAM_NAME] = diskEncryptionStatus;
|
||||
} else if (bootstrapPackageStatus && isPremiumTier) {
|
||||
newQueryParams.bootstrap_package = bootstrapPackageStatus;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
line-height: 1.5;
|
||||
background-color: $ui-light-grey;
|
||||
border: solid 1px $ui-fleet-black-10;
|
||||
border-radius: 4px;
|
||||
border-radius: $border-radius;
|
||||
font-size: $small;
|
||||
padding: 9.5px 12px 9.5px 36px;
|
||||
color: $core-fleet-blue;
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
color: $core-vibrant-red;
|
||||
border: 1px solid $core-vibrant-red;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
border-radius: $border-radius;
|
||||
|
||||
&:focus {
|
||||
border-color: $ui-error;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { IDropdownOption } from "interfaces/dropdownOption";
|
|||
|
||||
// @ts-ignore
|
||||
import Dropdown from "components/forms/fields/Dropdown";
|
||||
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||
import { DiskEncryptionStatus } from "interfaces/mdm";
|
||||
|
||||
const baseClass = "disk-encryption-status-filter";
|
||||
|
||||
|
|
@ -42,8 +42,8 @@ const DISK_ENCRYPTION_STATUS_OPTIONS: IDropdownOption[] = [
|
|||
];
|
||||
|
||||
interface IDiskEncryptionStatusFilterProps {
|
||||
diskEncryptionStatus: FileVaultProfileStatus;
|
||||
onChange: (value: FileVaultProfileStatus) => void;
|
||||
diskEncryptionStatus: DiskEncryptionStatus;
|
||||
onChange: (value: DiskEncryptionStatus) => void;
|
||||
}
|
||||
|
||||
const DiskEncryptionStatusFilter = ({
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid $ui-fleet-black-25;
|
||||
border-radius: 4px;
|
||||
border-radius: $border-radius;
|
||||
box-shadow: none;
|
||||
color: $core-fleet-black;
|
||||
font-size: $xx-small;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
IOperatingSystemVersion,
|
||||
} from "interfaces/operating_system";
|
||||
import {
|
||||
FileVaultProfileStatus,
|
||||
DiskEncryptionStatus,
|
||||
BootstrapPackageStatus,
|
||||
IMdmSolution,
|
||||
MDM_ENROLLMENT_STATUS,
|
||||
|
|
@ -15,7 +15,10 @@ import {
|
|||
import { IMunkiIssuesAggregate } from "interfaces/macadmins";
|
||||
import { ISoftware } from "interfaces/software";
|
||||
import { IPolicy } from "interfaces/policy";
|
||||
import { MacSettingsStatusQueryParam } from "services/entities/hosts";
|
||||
import {
|
||||
DISK_ENCRYPTION_QUERY_PARAM_NAME,
|
||||
MacSettingsStatusQueryParam,
|
||||
} from "services/entities/hosts";
|
||||
|
||||
import {
|
||||
PLATFORM_LABEL_DISPLAY_NAMES,
|
||||
|
|
@ -60,7 +63,7 @@ interface IHostsFilterBlockProps {
|
|||
osVersions?: IOperatingSystemVersion[];
|
||||
softwareDetails: ISoftware | null;
|
||||
mdmSolutionDetails: IMdmSolution | null;
|
||||
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
||||
bootstrapPackageStatus?: BootstrapPackageStatus;
|
||||
};
|
||||
selectedLabel?: ILabel;
|
||||
|
|
@ -68,9 +71,7 @@ interface IHostsFilterBlockProps {
|
|||
handleClearRouteParam: () => void;
|
||||
handleClearFilter: (omitParams: string[]) => void;
|
||||
onChangePoliciesFilter: (response: PolicyResponse) => void;
|
||||
onChangeDiskEncryptionStatusFilter: (
|
||||
response: FileVaultProfileStatus
|
||||
) => void;
|
||||
onChangeDiskEncryptionStatusFilter: (response: DiskEncryptionStatus) => void;
|
||||
onChangeBootstrapPackageStatusFilter: (
|
||||
response: BootstrapPackageStatus
|
||||
) => void;
|
||||
|
|
@ -376,8 +377,8 @@ const HostsFilterBlock = ({
|
|||
onChange={onChangeDiskEncryptionStatusFilter}
|
||||
/>
|
||||
<FilterPill
|
||||
label="macOS settings: Disk encryption"
|
||||
onClear={() => handleClearFilter(["macos_settings_disk_encryption"])}
|
||||
label="OS settings: Disk encryption"
|
||||
onClear={() => handleClearFilter([DISK_ENCRYPTION_QUERY_PARAM_NAME])}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ const DeviceUserPage = ({
|
|||
showRefetchSpinner={showRefetchSpinner}
|
||||
onRefetchHost={onRefetchHost}
|
||||
renderActionButtons={renderActionButtons}
|
||||
osSettings={host?.mdm.os_settings}
|
||||
deviceUser
|
||||
/>
|
||||
<TabsWrapper>
|
||||
|
|
@ -489,6 +490,7 @@ const DeviceUserPage = ({
|
|||
)}
|
||||
{showMacSettingsModal && (
|
||||
<MacSettingsModal
|
||||
platform={host?.platform}
|
||||
hostMDMData={host?.mdm}
|
||||
onClose={toggleMacSettingsModal}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import queryAPI from "services/entities/queries";
|
|||
import teamAPI, { ILoadTeamsResponse } from "services/entities/teams";
|
||||
import { AppContext } from "context/app";
|
||||
import { PolicyContext } from "context/policy";
|
||||
import { QueryContext } from "context/query";
|
||||
import { NotificationContext } from "context/notification";
|
||||
import {
|
||||
IHost,
|
||||
|
|
@ -26,6 +27,7 @@ import { ILabel } from "interfaces/label";
|
|||
import { IHostPolicy } from "interfaces/policy";
|
||||
import { IQueryStats } from "interfaces/query_stats";
|
||||
import { ISoftware } from "interfaces/software";
|
||||
import { DEFAULT_TARGETS_BY_TYPE } from "interfaces/target";
|
||||
import { ITeam } from "interfaces/team";
|
||||
import {
|
||||
IListQueriesResponse,
|
||||
|
|
@ -39,8 +41,13 @@ import MainContent from "components/MainContent";
|
|||
import InfoBanner from "components/InfoBanner";
|
||||
import BackLink from "components/BackLink";
|
||||
|
||||
import { normalizeEmptyValues, wrapFleetHelper } from "utilities/helpers";
|
||||
import {
|
||||
normalizeEmptyValues,
|
||||
wrapFleetHelper,
|
||||
TAGGED_TEMPLATES,
|
||||
} from "utilities/helpers";
|
||||
import permissions from "utilities/permissions";
|
||||
import { DEFAULT_QUERY } from "utilities/constants";
|
||||
|
||||
import HostSummaryCard from "../cards/HostSummary";
|
||||
import AboutCard from "../cards/About";
|
||||
|
|
@ -65,6 +72,7 @@ import HostActionDropdown from "./HostActionsDropdown/HostActionsDropdown";
|
|||
import MacSettingsModal from "../MacSettingsModal";
|
||||
import BootstrapPackageModal from "./modals/BootstrapPackageModal";
|
||||
import SelectQueryModal from "./modals/SelectQueryModal";
|
||||
import { isSupportedPlatform } from "./modals/DiskEncryptionKeyModal/DiskEncryptionKeyModal";
|
||||
|
||||
const baseClass = "host-details";
|
||||
|
||||
|
|
@ -99,12 +107,6 @@ interface IHostDetailsSubNavItem {
|
|||
pathname: string;
|
||||
}
|
||||
|
||||
const TAGGED_TEMPLATES = {
|
||||
queryByHostRoute: (hostId: number | undefined | null) => {
|
||||
return `${hostId ? `?host_ids=${hostId}` : ""}`;
|
||||
},
|
||||
};
|
||||
|
||||
const HostDetailsPage = ({
|
||||
route,
|
||||
router,
|
||||
|
|
@ -135,6 +137,7 @@ const HostDetailsPage = ({
|
|||
setLastEditedQueryCritical,
|
||||
setPolicyTeamId,
|
||||
} = useContext(PolicyContext);
|
||||
const { setSelectedQueryTargetsByType } = useContext(QueryContext);
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
const handlePageError = useErrorHandler();
|
||||
|
|
@ -521,12 +524,15 @@ const HostDetailsPage = ({
|
|||
};
|
||||
|
||||
const onQueryHostCustom = () => {
|
||||
setLastEditedQueryBody(DEFAULT_QUERY.query);
|
||||
setSelectedQueryTargetsByType(DEFAULT_TARGETS_BY_TYPE);
|
||||
router.push(
|
||||
PATHS.NEW_QUERY() + TAGGED_TEMPLATES.queryByHostRoute(host?.id)
|
||||
);
|
||||
};
|
||||
|
||||
const onQueryHostSaved = (selectedQuery: ISchedulableQuery) => {
|
||||
setSelectedQueryTargetsByType(DEFAULT_TARGETS_BY_TYPE);
|
||||
router.push(
|
||||
PATHS.EDIT_QUERY(selectedQuery.id) +
|
||||
TAGGED_TEMPLATES.queryByHostRoute(host?.id)
|
||||
|
|
@ -720,6 +726,7 @@ const HostDetailsPage = ({
|
|||
showRefetchSpinner={showRefetchSpinner}
|
||||
onRefetchHost={onRefetchHost}
|
||||
renderActionButtons={renderActionButtons}
|
||||
osSettings={host?.mdm.os_settings}
|
||||
/>
|
||||
<TabsWrapper>
|
||||
<Tabs
|
||||
|
|
@ -845,6 +852,7 @@ const HostDetailsPage = ({
|
|||
)}
|
||||
{showMacSettingsModal && (
|
||||
<MacSettingsModal
|
||||
platform={host?.platform}
|
||||
hostMDMData={host?.mdm}
|
||||
onClose={toggleMacSettingsModal}
|
||||
/>
|
||||
|
|
@ -852,12 +860,15 @@ const HostDetailsPage = ({
|
|||
{showUnenrollMdmModal && !!host && (
|
||||
<UnenrollMdmModal hostId={host.id} onClose={toggleUnenrollMdmModal} />
|
||||
)}
|
||||
{showDiskEncryptionModal && host && (
|
||||
<DiskEncryptionKeyModal
|
||||
hostId={host.id}
|
||||
onCancel={() => setShowDiskEncryptionModal(false)}
|
||||
/>
|
||||
)}
|
||||
{showDiskEncryptionModal &&
|
||||
host &&
|
||||
isSupportedPlatform(host.platform) && (
|
||||
<DiskEncryptionKeyModal
|
||||
platform={host.platform}
|
||||
hostId={host.id}
|
||||
onCancel={() => setShowDiskEncryptionModal(false)}
|
||||
/>
|
||||
)}
|
||||
{showBootstrapPackageModal &&
|
||||
bootstrapPackageData.details &&
|
||||
bootstrapPackageData.name && (
|
||||
|
|
|
|||
|
|
@ -9,15 +9,32 @@ import CustomLink from "components/CustomLink";
|
|||
import Button from "components/buttons/Button";
|
||||
import InputFieldHiddenContent from "components/forms/fields/InputFieldHiddenContent";
|
||||
import DataError from "components/DataError";
|
||||
import { SupportedPlatform } from "interfaces/platform";
|
||||
|
||||
const baseClass = "disk-encryption-key-modal";
|
||||
|
||||
// currently these are the only supported platforms for the disk encryption
|
||||
// key modal.
|
||||
export type ModalSupportedPlatform = Extract<
|
||||
SupportedPlatform,
|
||||
"darwin" | "windows"
|
||||
>;
|
||||
|
||||
// Checks to see if the platform is supported by the modal.
|
||||
export const isSupportedPlatform = (
|
||||
platform: string
|
||||
): platform is ModalSupportedPlatform => {
|
||||
return ["darwin", "windows"].includes(platform);
|
||||
};
|
||||
|
||||
interface IDiskEncryptionKeyModal {
|
||||
platform: ModalSupportedPlatform;
|
||||
hostId: number;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const DiskEncryptionKeyModal = ({
|
||||
platform,
|
||||
hostId,
|
||||
onCancel,
|
||||
}: IDiskEncryptionKeyModal) => {
|
||||
|
|
@ -33,6 +50,18 @@ const DiskEncryptionKeyModal = ({
|
|||
select: (data) => data.encryption_key.key,
|
||||
});
|
||||
|
||||
const isMacOS = platform === "darwin";
|
||||
const descriptionText = isMacOS
|
||||
? "The disk encryption key refers to the FileVault recovery key for macOS."
|
||||
: "The disk encryption key refers to the BitLocker recovery key for Windows.";
|
||||
|
||||
const recoveryText = isMacOS
|
||||
? "Use this key to log in to the host if you forgot the password."
|
||||
: "Use this key to unlock the encrypted drive.";
|
||||
const recoveryUrl = isMacOS
|
||||
? "https://fleetdm.com/docs/using-fleet/mdm-disk-encryption#reset-a-macos-hosts-password-using-the-disk-encryption-key"
|
||||
: "https://fleetdm.com/docs/using-fleet/mdm-disk-encryption#unlock-a-windows-hosts-drive-using-the-disk-encryption-key";
|
||||
|
||||
return (
|
||||
<Modal title="Disk encryption key" onExit={onCancel} className={baseClass}>
|
||||
{encryptionKeyError ? (
|
||||
|
|
@ -40,15 +69,12 @@ const DiskEncryptionKeyModal = ({
|
|||
) : (
|
||||
<>
|
||||
<InputFieldHiddenContent value={encrpytionKey ?? ""} />
|
||||
<p>{descriptionText}</p>
|
||||
<p>
|
||||
The disk encryption key refers to the FileVault recovery key for
|
||||
macOS.
|
||||
</p>
|
||||
<p>
|
||||
Use this key to log in to the host if you forgot the password.{" "}
|
||||
{recoveryText}{" "}
|
||||
<CustomLink
|
||||
text="View recovery instructions"
|
||||
url="https://fleetdm.com/docs/using-fleet/mdm-disk-encryption#reset-a-macos-hosts-password-using-the-disk-encryption-key"
|
||||
url={recoveryUrl}
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
&__copy-message {
|
||||
background-color: $ui-light-grey;
|
||||
border: solid 1px #e2e4ea;
|
||||
border-radius: 10px;
|
||||
border-radius: $border-radius-xlarge;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./MacSettingsIndicator";
|
||||
|
|
@ -7,20 +7,28 @@ import MacSettingsTable from "./MacSettingsTable";
|
|||
import { generateTableData } from "./MacSettingsTable/MacSettingsTableConfig";
|
||||
|
||||
interface IMacSettingsModalProps {
|
||||
hostMDMData?: Pick<IHostMdmData, "profiles" | "macos_settings">;
|
||||
platform?: string;
|
||||
hostMDMData?: IHostMdmData;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const baseClass = "mac-settings-modal";
|
||||
|
||||
const MacSettingsModal = ({ hostMDMData, onClose }: IMacSettingsModalProps) => {
|
||||
const memoizedTableData = useMemo(() => generateTableData(hostMDMData), [
|
||||
hostMDMData,
|
||||
]);
|
||||
const MacSettingsModal = ({
|
||||
platform,
|
||||
hostMDMData,
|
||||
onClose,
|
||||
}: IMacSettingsModalProps) => {
|
||||
const memoizedTableData = useMemo(
|
||||
() => generateTableData(hostMDMData, platform),
|
||||
[hostMDMData, platform]
|
||||
);
|
||||
|
||||
if (!platform) return null;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="macOS settings"
|
||||
title="OS settings"
|
||||
onExit={onClose}
|
||||
className={baseClass}
|
||||
width="large"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ import {
|
|||
MacMdmProfileOperationType,
|
||||
} from "interfaces/mdm";
|
||||
|
||||
import { MacSettingsTableStatusValue } from "../MacSettingsTableConfig";
|
||||
import {
|
||||
isMdmProfileStatus,
|
||||
MacSettingsTableStatusValue,
|
||||
} from "../MacSettingsTableConfig";
|
||||
import TooltipContent, {
|
||||
TooltipInnerContentFunc,
|
||||
TooltipInnerContentOption,
|
||||
|
|
@ -41,8 +44,8 @@ const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
|
|||
iconName: "pending-partial",
|
||||
tooltip: (innerProps) =>
|
||||
innerProps.isDiskEncryptionProfile
|
||||
? "The host will receive the MDM command to install the disk encryption profile when the " +
|
||||
"host comes online."
|
||||
? "The hosts will receive the MDM command to turn on disk encryption " +
|
||||
"when the hosts come online."
|
||||
: "The host will receive the MDM command to install the configuration profile when the " +
|
||||
"host comes online.",
|
||||
},
|
||||
|
|
@ -56,8 +59,8 @@ const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
|
|||
iconName: "success",
|
||||
tooltip: (innerProps) =>
|
||||
innerProps.isDiskEncryptionProfile
|
||||
? "The host turned disk encryption on and " +
|
||||
"sent their key to Fleet. Fleet verified with osquery."
|
||||
? "The host turned disk encryption on and sent the key to Fleet. " +
|
||||
"Fleet verified with osquery."
|
||||
: "The host installed the configuration profile. Fleet verified with osquery.",
|
||||
},
|
||||
verifying: {
|
||||
|
|
@ -65,8 +68,9 @@ const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
|
|||
iconName: "success-partial",
|
||||
tooltip: (innerProps) =>
|
||||
innerProps.isDiskEncryptionProfile
|
||||
? "The host acknowledged the MDM command to install disk encryption profile. Fleet is " +
|
||||
"verifying with osquery and retrieving the disk encryption key. This may take up to one hour."
|
||||
? "The host acknowledged the MDM command to turn on disk encryption. " +
|
||||
"Fleet is verifying with osquery and retrieving the disk encryption key. " +
|
||||
"This may take up to one hour."
|
||||
: "The host acknowledged the MDM command to install the configuration profile. Fleet is " +
|
||||
"verifying with osquery.",
|
||||
},
|
||||
|
|
@ -98,9 +102,41 @@ const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
|
|||
},
|
||||
};
|
||||
|
||||
type WindowsDiskEncryptionDisplayConfig = Omit<
|
||||
OperationTypeOption,
|
||||
"action_required"
|
||||
>;
|
||||
|
||||
const WINDOWS_DISK_ENCRYPTION_DISPLAY_CONFIG: WindowsDiskEncryptionDisplayConfig = {
|
||||
verified: {
|
||||
statusText: "Verified",
|
||||
iconName: "success",
|
||||
tooltip: () =>
|
||||
"The host turned disk encryption on and sent the key to Fleet. Fleet verified with osquery.",
|
||||
},
|
||||
verifying: {
|
||||
statusText: "Verifying",
|
||||
iconName: "success-partial",
|
||||
tooltip: () =>
|
||||
"The host acknowledged the MDM command to turn on disk encryption. Fleet is verifying with osquery and retrieving " +
|
||||
"the disk encryption key. This may take up to one hour.",
|
||||
},
|
||||
pending: {
|
||||
statusText: "Enforcing (pending)",
|
||||
iconName: "pending-partial",
|
||||
tooltip: () =>
|
||||
"The host will receive the MDM command to turn on disk encryption when the host comes online.",
|
||||
},
|
||||
failed: {
|
||||
statusText: "Failed",
|
||||
iconName: "error",
|
||||
tooltip: null,
|
||||
},
|
||||
};
|
||||
|
||||
interface IMacSettingStatusCellProps {
|
||||
status: MacSettingsTableStatusValue;
|
||||
operationType: MacMdmProfileOperationType;
|
||||
operationType: MacMdmProfileOperationType | null;
|
||||
profileName: string;
|
||||
}
|
||||
|
||||
|
|
@ -108,8 +144,18 @@ const MacSettingStatusCell = ({
|
|||
status,
|
||||
operationType,
|
||||
profileName = "",
|
||||
}: IMacSettingStatusCellProps): JSX.Element => {
|
||||
const diplayOption = PROFILE_DISPLAY_CONFIG[operationType]?.[status];
|
||||
}: IMacSettingStatusCellProps) => {
|
||||
let displayOption: ProfileDisplayOption = null;
|
||||
|
||||
// windows hosts do not have an operation type at the moment and their display options are
|
||||
// different than mac hosts.
|
||||
if (!operationType && isMdmProfileStatus(status)) {
|
||||
displayOption = WINDOWS_DISK_ENCRYPTION_DISPLAY_CONFIG[status];
|
||||
}
|
||||
|
||||
if (operationType) {
|
||||
displayOption = PROFILE_DISPLAY_CONFIG[operationType]?.[status];
|
||||
}
|
||||
|
||||
const isDeviceUser = window.location.pathname
|
||||
.toLowerCase()
|
||||
|
|
@ -118,8 +164,8 @@ const MacSettingStatusCell = ({
|
|||
const isDiskEncryptionProfile =
|
||||
profileName === FLEET_FILEVAULT_PROFILE_DISPLAY_NAME;
|
||||
|
||||
if (diplayOption) {
|
||||
const { statusText, iconName, tooltip } = diplayOption;
|
||||
if (displayOption) {
|
||||
const { statusText, iconName, tooltip } = displayOption;
|
||||
const tooltipId = uniqueId();
|
||||
return (
|
||||
<span className={baseClass}>
|
||||
|
|
|
|||
|
|
@ -5,20 +5,27 @@ import { IHostMdmData } from "interfaces/host";
|
|||
import {
|
||||
FLEET_FILEVAULT_PROFILE_DISPLAY_NAME,
|
||||
// FLEET_FILEVAULT_PROFILE_IDENTIFIER,
|
||||
IHostMacMdmProfile,
|
||||
IHostMdmProfile,
|
||||
MdmProfileStatus,
|
||||
isWindowsDiskEncryptionStatus,
|
||||
} from "interfaces/mdm";
|
||||
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
|
||||
import TruncatedTextCell from "components/TableContainer/DataTable/TruncatedTextCell";
|
||||
import MacSettingStatusCell from "./MacSettingStatusCell";
|
||||
import { generateWinDiskEncryptionProfile } from "../../helpers";
|
||||
|
||||
export interface IMacSettingsTableRow
|
||||
extends Omit<IHostMacMdmProfile, "status"> {
|
||||
export interface IMacSettingsTableRow extends Omit<IHostMdmProfile, "status"> {
|
||||
status: MacSettingsTableStatusValue;
|
||||
}
|
||||
|
||||
export type MacSettingsTableStatusValue = MdmProfileStatus | "action_required";
|
||||
|
||||
export const isMdmProfileStatus = (
|
||||
status: string
|
||||
): status is MdmProfileStatus => {
|
||||
return status !== "action_required";
|
||||
};
|
||||
|
||||
interface IHeaderProps {
|
||||
column: {
|
||||
title: string;
|
||||
|
|
@ -92,20 +99,41 @@ const tableHeaders: IDataColumn[] = [
|
|||
];
|
||||
|
||||
export const generateTableData = (
|
||||
hostMDMData?: Pick<IHostMdmData, "profiles" | "macos_settings">
|
||||
hostMDMData?: IHostMdmData,
|
||||
platform?: string
|
||||
) => {
|
||||
if (!platform) return [];
|
||||
|
||||
let rows: IMacSettingsTableRow[] = [];
|
||||
if (!hostMDMData) {
|
||||
return rows;
|
||||
}
|
||||
|
||||
if (
|
||||
platform === "windows" &&
|
||||
hostMDMData.os_settings?.disk_encryption.status &&
|
||||
isWindowsDiskEncryptionStatus(
|
||||
hostMDMData.os_settings.disk_encryption.status
|
||||
)
|
||||
) {
|
||||
rows.push(
|
||||
generateWinDiskEncryptionProfile(
|
||||
hostMDMData.os_settings.disk_encryption.status
|
||||
)
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
const { profiles, macos_settings } = hostMDMData;
|
||||
|
||||
if (!profiles) {
|
||||
return rows;
|
||||
}
|
||||
rows = profiles;
|
||||
|
||||
if (macos_settings?.disk_encryption === "action_required") {
|
||||
if (
|
||||
platform === "darwin" &&
|
||||
macos_settings?.disk_encryption === "action_required"
|
||||
) {
|
||||
rows = profiles.map((p) => {
|
||||
// TODO: this is a brittle check for the filevault profile
|
||||
// it would be better to match on the identifier but it is not
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
import React from "react";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import MacSettingsIndicator from "./MacSettingsIndicator";
|
||||
import ProfileStatusIndicator from "./ProfileStatusIndicator";
|
||||
|
||||
describe("MacSettingsIndicator", () => {
|
||||
describe("ProfileStatusIndicator component", () => {
|
||||
it("Renders the text and icon", () => {
|
||||
const indicatorText = "test text";
|
||||
render(
|
||||
<MacSettingsIndicator indicatorText={indicatorText} iconName="success" />
|
||||
<ProfileStatusIndicator
|
||||
indicatorText={indicatorText}
|
||||
iconName="success"
|
||||
/>
|
||||
);
|
||||
const renderedIndicatorText = screen.getByText(indicatorText);
|
||||
const renderedIcon = screen.getByTestId("success-icon");
|
||||
|
|
@ -19,7 +22,7 @@ describe("MacSettingsIndicator", () => {
|
|||
const indicatorText = "test text";
|
||||
const tooltipText = "test tooltip text";
|
||||
render(
|
||||
<MacSettingsIndicator
|
||||
<ProfileStatusIndicator
|
||||
indicatorText={indicatorText}
|
||||
iconName="success"
|
||||
tooltip={{ tooltipText }}
|
||||
|
|
@ -42,7 +45,7 @@ describe("MacSettingsIndicator", () => {
|
|||
document.body.appendChild(newDiv);
|
||||
};
|
||||
render(
|
||||
<MacSettingsIndicator
|
||||
<ProfileStatusIndicator
|
||||
indicatorText={indicatorText}
|
||||
iconName="success"
|
||||
onClick={() => {
|
||||
|
|
@ -4,9 +4,9 @@ import { IconNames } from "components/icons";
|
|||
import Icon from "components/Icon";
|
||||
import Button from "components/buttons/Button";
|
||||
|
||||
const baseClass = "settings-indicator";
|
||||
const baseClass = "profile-status-indicator";
|
||||
|
||||
export interface IMacSettingsIndicator {
|
||||
export interface IProfileStatusIndicatorProps {
|
||||
indicatorText: string;
|
||||
iconName: IconNames;
|
||||
onClick?: () => void;
|
||||
|
|
@ -16,12 +16,12 @@ export interface IMacSettingsIndicator {
|
|||
};
|
||||
}
|
||||
|
||||
const MacSettingsIndicator = ({
|
||||
const ProfileStatusIndicator = ({
|
||||
indicatorText,
|
||||
iconName,
|
||||
onClick,
|
||||
tooltip,
|
||||
}: IMacSettingsIndicator): JSX.Element => {
|
||||
}: IProfileStatusIndicatorProps) => {
|
||||
const getIndicatorTextWrapped = () => {
|
||||
if (onClick && tooltip?.tooltipText) {
|
||||
return (
|
||||
|
|
@ -103,4 +103,4 @@ const MacSettingsIndicator = ({
|
|||
);
|
||||
};
|
||||
|
||||
export default MacSettingsIndicator;
|
||||
export default ProfileStatusIndicator;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
.settings-indicator {
|
||||
.profile-status-indicator {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue