From 1675b4ee736b3c312bb659528039814aac1368c2 Mon Sep 17 00:00:00 2001
From: Rachael Shaw
Date: Wed, 27 Mar 2024 12:52:05 -0500
Subject: [PATCH 01/64] Update agent options for canary team (#17901)
- This is to explore queries for
https://github.com/fleetdm/fleet/issues/16899
---
it-and-security/teams/workstations-canary.yml | 26 ++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/it-and-security/teams/workstations-canary.yml b/it-and-security/teams/workstations-canary.yml
index d2c42b0cd7..e5ad3636eb 100644
--- a/it-and-security/teams/workstations-canary.yml
+++ b/it-and-security/teams/workstations-canary.yml
@@ -9,7 +9,31 @@ team_settings:
secrets:
- secret: $DOGFOOD_WORKSTATIONS_CANARY_ENROLL_SECRET
agent_options:
- path: ../lib/agent-options.yml
+ config:
+ decorators:
+ load:
+ - SELECT uuid AS host_uuid FROM system_info;
+ - SELECT hostname AS hostname FROM system_info;
+ options:
+ disable_distributed: false
+ distributed_interval: 10
+ distributed_plugin: tls
+ distributed_tls_max_attempts: 3
+ logger_tls_endpoint: /api/osquery/log
+ logger_tls_period: 10
+ pack_delimiter: /
+ overrides:
+ platforms:
+ darwin:
+ auto_table_construction:
+ tcc:
+ path: /Library/Application Support/com.apple.TCC/TCC.db
+ query: 'select service, client, auth_value, auth_reason from access'
+ columns:
+ - service
+ - client
+ - auth_value
+ - auth_reason
controls:
enable_disk_encryption: true
macos_settings:
From 4d2d704bb9665345aab596f57327a4431ca0c093 Mon Sep 17 00:00:00 2001
From: George Karr
Date: Wed, 27 Mar 2024 14:02:35 -0500
Subject: [PATCH 02/64] georgekarrv publish release (#17870)
- **Added confirmation for tag**
- **Adding npm publish**
---
tools/release/patch_release.sh | 90 +++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 2 deletions(-)
diff --git a/tools/release/patch_release.sh b/tools/release/patch_release.sh
index 30e61662b8..0acd0ce7bf 100755
--- a/tools/release/patch_release.sh
+++ b/tools/release/patch_release.sh
@@ -78,6 +78,7 @@ usage() {
echo " -r, --release_notes Update the release notes in the named release on github and exit (requires changelog output from running the script previously)."
echo " -s, --start_version Set the target starting version (can also be the first positional arg) for the release, defaults to latest release on github"
echo " -t, --target_date Set the target date for the release, defaults to today if not provided"
+ echo " -u, --publish_release Set's release from draft to release, deploys to dogfood."
echo " -v, --target_version Set the target version for the release"
echo ""
echo "Environment Variables:"
@@ -219,6 +220,42 @@ update_release_notes() {
fi
}
+publish() {
+ gh release edit --draft=false --latest $next_tag
+ gh workflow run dogfood-deploy.yml -f DOCKER_IMAGE=fleetdm/fleet:$next_ver
+ show_spinner 200
+ echo "========================================================================="
+ echo "Update osquery Slack Fleet channel topic to say the correct version $next_ver"
+ echo "========================================================================="
+ dogfood_deploy=`gh run list --workflow=dogfood-deploy.yml --status in_progress -L 1 --json url | jq -r '.[] | .url'`
+ cd tools/fleetctl-npm && npm publish
+
+ issues=`gh issue list -m $target_milestone --json number | jq -r '.[] | .number'`
+ for iss in $issues; do
+ echo "Closing #$iss"
+ gh issue close $iss
+ done
+
+ echo "Closing milestone"
+ gh api repos/fleetdm/fleet/milestones/$target_milestone_number -f state=closed
+
+ # Slack
+ slack_hook_url=https://hooks.slack.com/services
+ app_id=T019PP37ALW
+ general_channel_id=B06RZ60NUHX/tzaDZOvFCSvS2HC6rECi3Mvu
+ help_infra_channel_id=B06RLDFLC75/biuacbLxWRsDhv0hLA2qnLbX
+ help_eng_channel_id=B06RDTMUP1U/x2R36PXvW13KE6daxMiUK6W7
+ announce_text=":cloud: :rocket: The latest version of Fleet is $target_milestone.\nMore info: https://github.com/fleetdm/fleet/releases/tag/$next_tag\nUpgrade now: https://fleetdm.com/docs/deploying/upgrading-fleet"
+
+ curl -X POST -H 'Content-type: application/json' \
+ --data "{\"text\":\"$announce_text\"}" \
+ $slack_hook_url/$app_id/$general_channel_id
+
+ curl -X POST -H 'Content-type: application/json' \
+ --data "{\"text\":\"$announce_text\nDogfood Deployed $dogfood_deploy\"}" \
+ $slack_hook_url/$app_id/$help_infra_channel_id
+}
+
# Validate we have all commands required to perform this script
check_required_binaries
@@ -232,6 +269,7 @@ start_version=""
target_date=""
target_version=""
print_info=false
+publish_release=false
release_notes=false
# Parse long options manually
@@ -245,6 +283,7 @@ for arg in "$@"; do
"--minor") set -- "$@" "-m" ;;
"--open_api_key") set -- "$@" "-o" ;;
"--print") set -- "$@" "-p" ;;
+ "--publish_release") set -- "$@" "-u" ;;
"--release_notes") set -- "$@" "-r" ;;
"--start_version") set -- "$@" "-s" ;;
"--target_date") set -- "$@" "-t" ;;
@@ -254,7 +293,7 @@ for arg in "$@"; do
done
# Extract options and their arguments using getopts
-while getopts "cdfhmo:prs:t:v:" opt; do
+while getopts "cdfhmo:prs:t:uv:" opt; do
case "$opt" in
c) cherry_pick_resolved=true ;;
d) dry_run=true ;;
@@ -266,6 +305,7 @@ while getopts "cdfhmo:prs:t:v:" opt; do
r) release_notes=true ;;
s) start_version=$OPTARG ;;
t) target_date=$OPTARG ;;
+ u) publish_release=true ;;
v) target_version=$OPTARG ;;
?) usage; exit 1 ;;
esac
@@ -356,10 +396,15 @@ if [ "$force" = "false" ]; then
;;
esac
fi
+# 4.47.2
start_milestone="${start_version:1}"
+# 4.47.3
target_milestone="${next_ver:1}"
+# 79
target_milestone_number=`gh api repos/:owner/:repo/milestones | jq -r ".[] | select(.title==\"$target_milestone\") | .number"`
+# patch-fleet-v4.47.3
target_patch_branch="patch-fleet-$next_ver"
+# fleet-v4.47.3
next_tag="fleet-$next_ver"
if [ "$print_info" = "true" ]; then
@@ -378,6 +423,11 @@ if [[ "$target_milestone_number" == "" ]]; then
fi
echo "Found milestone $target_milestone with number $target_milestone_number"
+if [ "$publish_release" = "true" ]; then
+ publish
+ exit 0
+fi
+
failed=false
if [ "$cherry_pick_resolved" = "false" ]; then
@@ -550,6 +600,20 @@ if [[ "$failed" == "false" ]]; then
echo -e "${output}" >> temp_changelog
echo "" >> temp_changelog
cp CHANGELOG.md old_changelog
+ cat temp_changelog
+ echo
+ echo "About to write changelog"
+ if [ "$force" = "false" ]; then
+ read -r -p "Does the above changelog look good (edit temp_changelog now to make changes) (n exits)? [y/N] " response
+ case "$response" in
+ [yY][eE][sS]|[yY])
+ echo
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ fi
cat temp_changelog > CHANGELOG.md
cat old_changelog >> CHANGELOG.md
rm -f old_changelog
@@ -561,6 +625,15 @@ if [[ "$failed" == "false" ]]; then
fi
git checkout -b $update_changelog_patch_branch
git add CHANGELOG.md
+ escaped_start_version=$(echo "$start_milestone" | sed 's/\./\\./g')
+ version_files=`ack -l --ignore-file=is:CHANGELOG.md "$escaped_start_version"`
+ unameOut="$(uname -s)"
+ case "${unameOut}" in
+ Linux*) echo "$version_files" | xargs sed -i "s/$escaped_start_version/$target_milestone/g";;
+ Darwin*) echo "$version_files" | xargs sed -i '' "s/$escaped_start_version/$target_milestone/g";;
+ *) echo "unknown distro to parse version"
+ esac
+ git add terraform charts infrastructure tools
git commit -m "Adding changes for patch $target_milestone"
git push origin $update_changelog_patch_branch -f
gh pr create -f -B $target_patch_branch
@@ -622,7 +695,7 @@ if [[ "$failed" == "false" ]]; then
echo `gh pr view $update_changelog_patch_branch --json url | jq -r .url`
echo
waiting=true
- while waiting; do
+ while $waiting; do
pr_state=`gh pr view $update_changelog_patch_branch --json state | jq -r .state`
if [[ "$pr_state" == "MERGED" ]]; then
waiting=false
@@ -632,6 +705,19 @@ if [[ "$failed" == "false" ]]; then
done
git pull origin $target_patch_branch
+
+ echo "About to tag to $next_tag"
+ if [ "$force" = "false" ]; then
+ read -r -p "Did all steps succeed and is the tag ready to push? [y/N] " response
+ case "$response" in
+ [yY][eE][sS]|[yY])
+ echo
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+ fi
git tag $next_tag
git push origin $next_tag
From 8aa1dcf84b2eba7829818140b9100950dec84334 Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 14:09:42 -0500
Subject: [PATCH 03/64] Move revenue report to Bizops (#17902)
---
handbook/business-operations/README.md | 28 +++++++++++++++++++
.../business-operations.rituals.yml | 10 +++++++
handbook/digital-experience/README.md | 27 ------------------
.../digital-experience.rituals.yml | 10 -------
4 files changed, 38 insertions(+), 37 deletions(-)
diff --git a/handbook/business-operations/README.md b/handbook/business-operations/README.md
index 491da34684..5ce2c08b2c 100644
--- a/handbook/business-operations/README.md
+++ b/handbook/business-operations/README.md
@@ -108,6 +108,34 @@ For Fleet's US contractors, running payroll is a manual process:
- Adjust time frame to match current payroll period (the 27th through 26th of the month)
- Sync hours and run contractor payroll.
+
+### Grant role-specific license to a team member (RevOps)
+Certain new team members, especially in go-to-market (GTM) roles, will need paid access to paid tools like Salesforce and LinkedIn Sales Navigator immediately on their first dayΒ with the company. Gong licenses that other departments need may [request them from BizOps](https://fleetdm.com/handbook/business-operations#contact-us) and we will make sure there is no license redundancy in that department. The table below can be used to determine which paid licenses they will need, based on their role:
+
+| Role | Salesforce CRM | Salesforce "Inbox" | LinkedIn _(paid)_ | Gong _(paid)_ | Zoom _(paid)_|
+|:-----------------|:---|:---|:----|:---|:---|
+| π AE | β
| β
| β
| β
| β
+| π CSM | β
| β
| β | β
| β
+| π SC | β
| β
| β | β | β
+| βοΈ PM | β | β | β | β
| β
+| βοΈ PD | β | β | β | β
| β
+| π¦ CEO | β
| β
| β
| β
| β
+| Other roles | β | β | β | β | β
+
+> **Warning:** Do NOT buy LinkedIn Recruiter. AEs and SDRs should use their personal Brex card to purchase the monthly [Core Sales Navigator](https://business.linkedin.com/sales-solutions/compare-plans) plan. Fleet does not use a company wide Sales Navigator account. The goal of Sales Navigator is to access to profile views and data, not InMail. Fleet does not send InMail.
+
+
+### Add a seat to Salesforce
+Here are the steps we take to grant appropriate Salesforce licenses to a new hire:
+- Go to ["My Account"](https://fleetdm.lightning.force.com/lightning/n/standard-OnlineSalesHome).
+- View contracts -> pick current contract.
+- Add the desired number of licenses.
+- Sign DocuSign sent to the email.
+- The order will be processed in ~30m.
+- Once the basic license has been added, you can create a new user using the new team member's `@fleetdm.com` email and assign a license to it.
+- To also assign a user an "Inbox license", go to the ["Setup" page](https://fleetdm.lightning.force.com/lightning/setup/SetupOneHome/home) and select "User > Permission sets". Find the [inbox permission set](https://fleetdm.lightning.force.com/lightning/setup/PermSets/page?address=%2F005%3Fid%3D0PS4x000002uUn2%26isUserEntityOverride%3D1%26SetupNode%3DPermSets%26sfdcIFrameOrigin%3Dhttps%253A%252F%252Ffleetdm.lightning.force.com%26clc%3D1) and assign it to the new team member.
+
+
### Run US commission payroll
- Update [commission calculator](https://docs.google.com/spreadsheets/d/1vw6Q7kCC7-FdG5Fgx3ghgUdQiF2qwxk6njgK6z8_O9U/edit) with new revenue from any deals that are closed/won (have a subscription agreement signed by both parties) and have an **effective start date** within the previous month.
- Find detailed notes on this process in [Notes - Run commission payroll in Gusto](https://docs.google.com/document/d/1FQLpGxvHPW6X801HYYLPs5y8o943mmasQD3m9k_c0so/edit#).
diff --git a/handbook/business-operations/business-operations.rituals.yml b/handbook/business-operations/business-operations.rituals.yml
index 3be2ee4b68..e5f2c58c76 100644
--- a/handbook/business-operations/business-operations.rituals.yml
+++ b/handbook/business-operations/business-operations.rituals.yml
@@ -42,6 +42,16 @@
autoIssue:
labels: [ "#g-business-operations" ]
repo: "confidential"
+-
+ task: "Revenue report" # TODO tie this to a responsibility
+ startedOn: "2024-02-12"
+ frequency: "Weekly"
+ description: "At the start of every week, check the Salesforce reports for past due invoices, non-invoiced opportunities, and past due renewals. Report any findings to in the `#g-sales` channel by mentioning Alex Mitchell and Mike McNeil."
+ moreInfoUrl:
+ dri: "jostableford"
+ autoIssue:
+ labels: [ "#g-digital-experience" ]
+ repo: "confidential"
-
task: "AP invoice monitoring" # TODO tie this to a responsibility
startedOn: "2024-04-01"
diff --git a/handbook/digital-experience/README.md b/handbook/digital-experience/README.md
index e8d0626b78..362735ede7 100644
--- a/handbook/digital-experience/README.md
+++ b/handbook/digital-experience/README.md
@@ -152,33 +152,6 @@ If the action fails, please complete the following steps:
3. Head to the fleetdm/fleet GitHub repository and re-run the Deploy Fleet Website action.
-### Grant role-specific license to a team member (RevOps)
-Certain new team members, especially in go-to-market (GTM) roles, will need paid access to paid tools like Salesforce and LinkedIn Sales Navigator immediately on their first dayΒ with the company. Gong licenses that other departments need may [request them from BizOps](https://fleetdm.com/handbook/business-operations#contact-us) and we will make sure there is no license redundancy in that department. The table below can be used to determine which paid licenses they will need, based on their role:
-
-| Role | Salesforce CRM | Salesforce "Inbox" | LinkedIn _(paid)_ | Gong _(paid)_ | Zoom _(paid)_|
-|:-----------------|:---|:---|:----|:---|:---|
-| π AE | β
| β
| β
| β
| β
-| π CSM | β
| β
| β | β
| β
-| π SC | β
| β
| β | β | β
-| βοΈ PM | β | β | β | β
| β
-| βοΈ PD | β | β | β | β
| β
-| π¦ CEO | β
| β
| β
| β
| β
-| Other roles | β | β | β | β | β
-
-> **Warning:** Do NOT buy LinkedIn Recruiter. AEs and SDRs should use their personal Brex card to purchase the monthly [Core Sales Navigator](https://business.linkedin.com/sales-solutions/compare-plans) plan. Fleet does not use a company wide Sales Navigator account. The goal of Sales Navigator is to access to profile views and data, not InMail. Fleet does not send InMail.
-
-
-### Add a seat to Salesforce
-Here are the steps we take to grant appropriate Salesforce licenses to a new hire:
-- Go to ["My Account"](https://fleetdm.lightning.force.com/lightning/n/standard-OnlineSalesHome).
-- View contracts -> pick current contract.
-- Add the desired number of licenses.
-- Sign DocuSign sent to the email.
-- The order will be processed in ~30m.
-- Once the basic license has been added, you can create a new user using the new team member's `@fleetdm.com` email and assign a license to it.
-- To also assign a user an "Inbox license", go to the ["Setup" page](https://fleetdm.lightning.force.com/lightning/setup/SetupOneHome/home) and select "User > Permission sets". Find the [inbox permission set](https://fleetdm.lightning.force.com/lightning/setup/PermSets/page?address=%2F005%3Fid%3D0PS4x000002uUn2%26isUserEntityOverride%3D1%26SetupNode%3DPermSets%26sfdcIFrameOrigin%3Dhttps%253A%252F%252Ffleetdm.lightning.force.com%26clc%3D1) and assign it to the new team member.
-
-
### Refresh event calendar
Fleet's public relations firm is directly responsible for the accuracy of event locations, attendance dates, and CFP deadlines in the event strategy workbook. At the end of every quarter, the PR firm updates every event in the ["Event strategy workbook"](https://docs.google.com/spreadsheets/d/1YQXAX2Q_WnGkAwMYjMbQpV3nbCj7gOBbv7Y0u4twxzQ/edit) (private Google doc) by following these steps:
1. Visit the latest website for each event.
diff --git a/handbook/digital-experience/digital-experience.rituals.yml b/handbook/digital-experience/digital-experience.rituals.yml
index 75e4244d02..fbb34ae2c2 100644
--- a/handbook/digital-experience/digital-experience.rituals.yml
+++ b/handbook/digital-experience/digital-experience.rituals.yml
@@ -48,16 +48,6 @@
description: "Prepare the CEO office minutes calendar event and meeting agenda"
moreInfoUrl: "https://fleetdm.com/handbook/digital-experience#prepare-for-ceo-office-minutes"
dri: "sampfluger88"
--
- task: "Revenue report" # TODO tie this to a responsibility
- startedOn: "2024-02-12"
- frequency: "Weekly"
- description: "At the start of every week, check the Salesforce reports for past due invoices, non-invoiced opportunities, and past due renewals. Report any findings to in the `#g-sales` channel by mentioning Alex Mitchell and Mike McNeil."
- moreInfoUrl:
- dri: "hughestaylor"
- autoIssue:
- labels: [ "#g-digital-experience" ]
- repo: "confidential"
-
task: "Refresh event calendar"
startedOn: "2023-12-31"
From cf531a242aab67012e71a51459614bd3606a6473 Mon Sep 17 00:00:00 2001
From: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Date: Wed, 27 Mar 2024 15:50:47 -0400
Subject: [PATCH 04/64] Update workstations.yml (#17906)
- Add policies Windows 11 CIS Benchmarks
- Remove Windows device health policies
---
.../lib/windows-device-health.policies.yml | 24 -------------------
it-and-security/teams/workstations.yml | 2 +-
2 files changed, 1 insertion(+), 25 deletions(-)
delete mode 100644 it-and-security/lib/windows-device-health.policies.yml
diff --git a/it-and-security/lib/windows-device-health.policies.yml b/it-and-security/lib/windows-device-health.policies.yml
deleted file mode 100644
index 4b92f5841e..0000000000
--- a/it-and-security/lib/windows-device-health.policies.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-- name: Windows - Enable screen saver after 20 minutes
- query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/DeviceLock/MaxInactivityTimeDeviceLock
" and CAST(mdm_command_output AS INT) <= 20;
- critical: false
- description: This policy checks if maximum amount of time (in minutes) the device is allowed to sit idle before the screen is locked. End users can select any value less than the specified maximum.
- resolution: "As an IT admin, to deploy a Windows profile with the MaxInactivityTimeDeviceLock option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-devicelock#maxinactivitytimedevicelock"
- platform: windows
-- name: Windows - Enable BitLocker
- query: SELECT * FROM bitlocker_info WHERE drive_letter='C:' AND protection_status = 1;
- critical: false
- description: As an IT admin, turn on disk encryption in Fleet.
- resolution: Ask your system administrator to turn on disk encryption in Fleet
- platform: windows
-- name: Windows - Disable guest account
- query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/LocalPoliciesSecurityOptions/Accounts_EnableGuestAccountStatus
" and CAST(mdm_command_output AS INT) = 0;
- critical: false
- description: This policy checks if the guest account is disabled. The Guest account allows unauthenticated network users to gain access to the system.
- resolution: "As an IT admin, deploy a Windows profile with the Accounts_EnableGuestAccountStatus option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-localpoliciessecurityoptions#accounts_enableguestaccountstatus"
- platform: windows
-- name: Windows - Require 10 character password
- query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/DeviceLock/DevicePasswordEnabled
" and CAST(mdm_command_output AS INT) = 0;
- critical: false
- description: This policy checks if the end user is required to enter a password, with at least 10 characters, to unlock the host.
- resolution: "As an IT admin, deploy a Windows profile with the DevicePasswordEnabled and MinDevicePasswordLength option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-devicelock"
- platform: windows
\ No newline at end of file
diff --git a/it-and-security/teams/workstations.yml b/it-and-security/teams/workstations.yml
index 95ca009dc3..c287420d0f 100644
--- a/it-and-security/teams/workstations.yml
+++ b/it-and-security/teams/workstations.yml
@@ -55,8 +55,8 @@ controls:
- path: ../lib/windows-turn-off-mdm.ps1
policies:
- path: ../lib/macos-device-health.policies.yml
- - path: ../lib/windows-device-health.policies.yml
- path: ../lib/linux-device-health.policies.yml
+ - path: ../../ee/cis/win-11/cis-policy-queries.yml
queries:
- path: ../lib/collect-failed-login-attempts.queries.yml
- path: ../lib/collect-usb-devices.queries.yml
From 465099fa31b3e1e953db476e0a53b875286bcd14 Mon Sep 17 00:00:00 2001
From: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Date: Wed, 27 Mar 2024 15:53:59 -0400
Subject: [PATCH 05/64] Update workstations-canary.yml (#17907)
- Forgot to update workstations (canary) as part of the following PR:
#17906
---
it-and-security/teams/workstations-canary.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it-and-security/teams/workstations-canary.yml b/it-and-security/teams/workstations-canary.yml
index e5ad3636eb..97d6a11d7a 100644
--- a/it-and-security/teams/workstations-canary.yml
+++ b/it-and-security/teams/workstations-canary.yml
@@ -80,7 +80,7 @@ controls:
- path: ../lib/windows-install-bitdefender.ps1
policies:
- path: ../lib/macos-device-health.policies.yml
- - path: ../lib/windows-device-health.policies.yml
+ - path: ../../ee/cis/win-11/cis-policy-queries.yml
- path: ../lib/linux-device-health.policies.yml
- name: chromeOS/macOS - Screenlock enabled
query: SELECT 1 FROM screenlock WHERE enabled = 1;
From c936896c1fa49e4b7b8843204e5205ed1e2f1e52 Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Wed, 27 Mar 2024 16:17:16 -0400
Subject: [PATCH 06/64] [tiny released bugs] Fleet UI: Fix 2 typos that include
a random character (#17908)
---
.../LogDestinationIndicator/LogDestinationIndicator.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx b/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
index 3bc7998618..4d88395155 100644
--- a/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
+++ b/frontend/components/LogDestinationIndicator/LogDestinationIndicator.tsx
@@ -60,7 +60,7 @@ const LogDestinationIndicator = ({
return (
<>
Each time a query runs, the data is sent to
- Amazon Kinesis Data Firehose.`
+ Amazon Kinesis Data Firehose.
>
);
case "kinesis":
@@ -81,7 +81,7 @@ const LogDestinationIndicator = ({
return (
<>
Each time a query runs, the data is
sent to Google Cloud Pub
- / Sub.`
+ / Sub.
>
);
case "kafta":
From c7c07d9112b563378c9acd1e7990813b89900c83 Mon Sep 17 00:00:00 2001
From: Grant Bilstad <82750216+pacamaster@users.noreply.github.com>
Date: Wed, 27 Mar 2024 14:58:37 -0600
Subject: [PATCH 07/64] Revert "Update workstations.yml" (#17910)
Reverts fleetdm/fleet#17906
---
.../lib/windows-device-health.policies.yml | 25 +++++++++++++++++++
it-and-security/teams/workstations.yml | 2 +-
2 files changed, 26 insertions(+), 1 deletion(-)
create mode 100644 it-and-security/lib/windows-device-health.policies.yml
diff --git a/it-and-security/lib/windows-device-health.policies.yml b/it-and-security/lib/windows-device-health.policies.yml
new file mode 100644
index 0000000000..5a15b90cc5
--- /dev/null
+++ b/it-and-security/lib/windows-device-health.policies.yml
@@ -0,0 +1,25 @@
+- name: Windows - Enable screen saver after 20 minutes
+ query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/DeviceLock/MaxInactivityTimeDeviceLock
" and CAST(mdm_command_output AS INT) <= 20;
+ critical: false
+ description: This policy checks if maximum amount of time (in minutes) the device is allowed to sit idle before the screen is locked. End users can select any value less than the specified maximum.
+ resolution: "As an IT admin, to deploy a Windows profile with the MaxInactivityTimeDeviceLock option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-devicelock#maxinactivitytimedevicelock"
+ platform: windows
+- name: Windows - Enable BitLocker
+ query: SELECT * FROM bitlocker_info WHERE drive_letter='C:' AND protection_status = 1;
+ critical: false
+ description: As an IT admin, turn on disk encryption in Fleet.
+ resolution: Ask your system administrator to turn on disk encryption in Fleet
+ platform: windows
+- name: Windows - Disable guest account
+ query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/LocalPoliciesSecurityOptions/Accounts_EnableGuestAccountStatus
" and CAST(mdm_command_output AS INT) = 0;
+ critical: false
+ description: This policy checks if the guest account is disabled. The Guest account allows unauthenticated network users to gain access to the system.
+ resolution: "As an IT admin, deploy a Windows profile with the Accounts_EnableGuestAccountStatus option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-localpoliciessecurityoptions#accounts_enableguestaccountstatus"
+ platform: windows
+- name: Windows - Require 10 character password
+ query: SELECT 1 FROM mdm_bridge where mdm_command_input = "1- ./Device/Vendor/MSFT/Policy/Result/DeviceLock/DevicePasswordEnabled
" and CAST(mdm_command_output AS INT) = 0;
+ critical: false
+ description: This policy checks if the end user is required to enter a password, with at least 10 characters, to unlock the host.
+ resolution: "As an IT admin, deploy a Windows profile with the DevicePasswordEnabled and MinDevicePasswordLength option documented here: https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-devicelock"
+ platform: windows
+
diff --git a/it-and-security/teams/workstations.yml b/it-and-security/teams/workstations.yml
index c287420d0f..95ca009dc3 100644
--- a/it-and-security/teams/workstations.yml
+++ b/it-and-security/teams/workstations.yml
@@ -55,8 +55,8 @@ controls:
- path: ../lib/windows-turn-off-mdm.ps1
policies:
- path: ../lib/macos-device-health.policies.yml
+ - path: ../lib/windows-device-health.policies.yml
- path: ../lib/linux-device-health.policies.yml
- - path: ../../ee/cis/win-11/cis-policy-queries.yml
queries:
- path: ../lib/collect-failed-login-attempts.queries.yml
- path: ../lib/collect-usb-devices.queries.yml
From 0014a2b102a1eb0cc90a71f55dab46d8fc250eff Mon Sep 17 00:00:00 2001
From: Grant Bilstad <82750216+pacamaster@users.noreply.github.com>
Date: Wed, 27 Mar 2024 14:59:04 -0600
Subject: [PATCH 08/64] Revert "Update workstations-canary.yml" (#17911)
Reverts fleetdm/fleet#17907
---
it-and-security/teams/workstations-canary.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/it-and-security/teams/workstations-canary.yml b/it-and-security/teams/workstations-canary.yml
index 97d6a11d7a..e5ad3636eb 100644
--- a/it-and-security/teams/workstations-canary.yml
+++ b/it-and-security/teams/workstations-canary.yml
@@ -80,7 +80,7 @@ controls:
- path: ../lib/windows-install-bitdefender.ps1
policies:
- path: ../lib/macos-device-health.policies.yml
- - path: ../../ee/cis/win-11/cis-policy-queries.yml
+ - path: ../lib/windows-device-health.policies.yml
- path: ../lib/linux-device-health.policies.yml
- name: chromeOS/macOS - Screenlock enabled
query: SELECT 1 FROM screenlock WHERE enabled = 1;
From 19c395a3ba648a0d702727d3d262445cd10d5d5e Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 16:44:06 -0500
Subject: [PATCH 09/64] Remove ritual (#17914)
---
handbook/digital-experience/digital-experience.rituals.yml | 7 -------
1 file changed, 7 deletions(-)
diff --git a/handbook/digital-experience/digital-experience.rituals.yml b/handbook/digital-experience/digital-experience.rituals.yml
index fbb34ae2c2..0bd5a43e9a 100644
--- a/handbook/digital-experience/digital-experience.rituals.yml
+++ b/handbook/digital-experience/digital-experience.rituals.yml
@@ -86,13 +86,6 @@
description: "Process the CEO's calendar"
moreInfoUrl: "https://fleetdm.com/handbook/digital-experience#process-the-ceos-calendar"
dri: "sampfluger88"
--
- task: "Fleet IT warehouse management"
- startedOn: "2023-07-29"
- frequency: "Weekly"
- description: "Fleet IT warehouse management"
- moreInfoUrl: "https://fleetdm.com/handbook/digital-experience#fleet-it-warehouse-management"
- dri: "sampfluger88"
-
task: "Send weekly update"
startedOn: "2023-09-15"
From 770a43d48da6b8e6f80bcf304a62770581838a95 Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 17:54:57 -0500
Subject: [PATCH 10/64] Remove Apprentice position (#17918)
...
---
handbook/company/open-positions.yml | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/handbook/company/open-positions.yml b/handbook/company/open-positions.yml
index fe09da8e55..3e1682d8ea 100644
--- a/handbook/company/open-positions.yml
+++ b/handbook/company/open-positions.yml
@@ -36,31 +36,6 @@
# - π οΈ Technical: You understand the software development processes. You understand that software quality matters.
# - π£ Openness: You are flexible and open to new ideas and ways of working.
# - β Bonus: Cybersecurity or IT background.
-
-- jobTitle: π Apprentice
- department: π Digital Experience
- hiringManagerName: Sam Pfluger
- hiringManagerGithubUsername: sampfluger88
- hiringManagerLinkedInUrl: https://www.linkedin.com/in/sampfluger88/
- responsibilities: |
- - π₯ Manage multiple calendars and schedules using Google Calendar and various forms of communication simultaneously.
- - π§βπ¬ Perform executive assistance processes as described in [https://fleetdm.com/handbook/digital-experience](https://fleetdm.com/handbook/digital-experience).
- - π Maintain and update the structure and content of the company handbook.
- - π£οΈ Act as secondary/backup point of contact for other departments for Digital Experience initiatives.
- - ποΈ Schedule travel arrangements for the CEO and other executives as needed.
- - βοΈ Help implement and drive change management for any new or modified processes and tools across the team and/or the organization.
- - π£ Record and communicate relevant information and decisions to the Digital Experience team and other departments.
- - π Collect and report Digital Experience KPIs.
- experience: |
- - πββοΈ Strong desire to build a technical and operational-based skill set.
- - π Detail-oriented, highly organized, and able to move quickly to solve complex problems using boring solutions.
- - π¦ Deep understanding of Google Suite (Gmail, Google Calendar, Google Sheets, Google Docs, etc.)
- - π« Experience dealing with sensitive personal information of team members and customers.
- - π οΈ Strong written and oral communication skills for general and technical topics.
- - π Capable of understanding and translating technical concepts and personas.
- - π€ Ability to work in a process-driven team-based environment.
- - π£ Openness: You are flexible and open to new ideas and ways of working.
- - β Bonus: Customer service/support background.
- jobTitle: π Quality Assurance Engineer
department: Engineering
hiringManagerName: George Karr
From 3588a7c3d816ea487e18bab82427ea939c4b26a5 Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 18:20:02 -0500
Subject: [PATCH 11/64] =?UTF-8?q?Replace=20"=F0=9F=8F=B9"=20with=20"?=
=?UTF-8?q?=F0=9F=8C=A6=EF=B8=8F"=20(#17920)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
...
---
handbook/company/README.md | 2 +-
handbook/customer-success/README.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/handbook/company/README.md b/handbook/company/README.md
index 289b378a1c..ef47e8116b 100644
--- a/handbook/company/README.md
+++ b/handbook/company/README.md
@@ -136,7 +136,7 @@ Fleet announces [support for Windows and Linux devices](https://fleetdm.com/anno
To provide clarity about decision-making, [responsibility](https://fleetdm.com/handbook/company/why-this-way#why-direct-responsibility), and resources, everyone at Fleet has a manager, and [every manager](https://fleetdm.com/handbook/company#management) has direct reports. Fleet's organizational chart is accessible company-wide as a sub-tab in ["π§βπ Fleeties" (private google doc)](https://docs.google.com/spreadsheets/d/1OSLn-ZCbGSjPusHPiR5dwQhheH1K8-xqyZdsOe9y7qc/edit#gid=0). On the other sub-tabs, you can also check out a world map of where everyone is located, hiring stats, and fun facts about each team member.
- π¦ [Business Operations](https://fleetdm.com/handbook/business-operations): The Business Operations department is directly responsible for these traditional functions: People, Finance, tax, compliance, Legal, and IT.
-- πΉ [Customer Success](https://fleetdm.com/handbook/customer-success): The customer success department is directly responsible for ensuring that customers and community members of Fleet achieve their desired outcomes with Fleet products and services.
+- π¦οΈ [Customer Success](https://fleetdm.com/handbook/customer-success): The customer success department is directly responsible for ensuring that customers and community members of Fleet achieve their desired outcomes with Fleet products and services.
- π [Sales](https://fleetdm.com/handbook/sales): The Sales department is directly responsible for attaining the revenue goals of Fleet and helping customers deliver on their objectives.
- π«§ [Demand](https://fleetdm.com/handbook/demand): The Demand department is directly responsible for growing awareness of Fleet and nurturing the community through participation in events, conversations, and other programs.
- π [Engineering](https://fleetdm.com/handbook/engineering): The Engineering department at Fleet is directly responsible for writing and maintaining the code for Fleet's core product.
diff --git a/handbook/customer-success/README.md b/handbook/customer-success/README.md
index 245cab5a98..9f8a266164 100644
--- a/handbook/customer-success/README.md
+++ b/handbook/customer-success/README.md
@@ -109,4 +109,4 @@ The following stubs are included only to make links backward compatible.
Please see [Handbook/customer-success#respond-to-messages-and-alerts](https://www.fleetdm.com/handbook/customer-success#respond-to-messages-and-alerts)
-
+
From c4a411b6d6fb18b914ee3e963096d9d23ab3d421 Mon Sep 17 00:00:00 2001
From: Eric
Date: Wed, 27 Mar 2024 19:10:24 -0500
Subject: [PATCH 12/64] Website: create `` component (#17846)
Closes: #17755
Changes:
- Created a new component: ``
- Added the logo-carousel component to the /start, /login, and /register
pages.
- Updated the /register and /login pages to match the latest wireframes.
---
.../js/components/logo-carousel.component.js | 92 +++++++++++++++++++
.../components/logo-carousel.component.less | 66 +++++++++++++
website/assets/styles/importer.less | 1 +
.../assets/styles/pages/entrance/login.less | 37 +++-----
.../assets/styles/pages/entrance/signup.less | 39 +++-----
website/assets/styles/pages/homepage.less | 76 ---------------
website/assets/styles/pages/start.less | 11 ++-
website/views/layouts/layout.ejs | 1 +
website/views/pages/entrance/login.ejs | 11 ++-
website/views/pages/entrance/signup.ejs | 10 +-
website/views/pages/homepage.ejs | 66 +------------
website/views/pages/start.ejs | 3 +
12 files changed, 218 insertions(+), 195 deletions(-)
create mode 100644 website/assets/js/components/logo-carousel.component.js
create mode 100644 website/assets/styles/components/logo-carousel.component.less
diff --git a/website/assets/js/components/logo-carousel.component.js b/website/assets/js/components/logo-carousel.component.js
new file mode 100644
index 0000000000..9cd93bf0e5
--- /dev/null
+++ b/website/assets/js/components/logo-carousel.component.js
@@ -0,0 +1,92 @@
+/**
+ *
+ * -----------------------------------------------------------------------------
+ * A row of logos that scroll infinitly to the left.
+ *
+ * @type {Component}
+ *
+ * -----------------------------------------------------------------------------
+ */
+
+parasails.registerComponent('logoCarousel', {
+ // ββββ¦βββββββββββ
+ // β βββ β¦ββ ββ βββββ
+ // β© β©ββββββ© βββ
+ props: [],
+
+ // β¦ββββ¦ββ¦ββ¦ββββ¦ βββββ¦ββββββ¦ββββ
+ // βββββ β ββ ββ£β βββ β β ββ£ β ββ£
+ // β©ββββ© β© β©β© β©β©ββ βββ β© β© β© β© βββ
+ data: function (){
+ return {
+ //β¦
+ };
+ },
+
+ // β¦ β¦ββ¦βββ¦ββ¦
+ // β ββ£ β ββββ
+ // β© β© β© β© β©β©ββ
+ template: `
+
+
+
+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+
+
+

+

+

+

+

+

+

+

+

+

+

+

+

+

+

+
+
+
+
+
+
+ `,
+
+ // β¦ β¦ββββββββββ¦ β¦ββββ¦ βββ
+ // β ββ β£ ββ£ β ββ¦ββ β ββ£
+ // β©βββ©β ββββββ β© ββββ©βββββ
+ beforeMount: function() {
+ //β¦
+ },
+ mounted: async function(){
+ //β¦
+ },
+ beforeDestroy: function() {
+ //β¦
+ },
+
+ // β¦βββββ¦βββββ¦ββββββββββ¦ββ¦βββββββββ
+ // ββββ β ββ£ β β¦ββ ββ£β β ββ βββββββ
+ // β©βββ β© ββββ©βββ© β©βββ β© β©βββββββββ
+ methods: {
+ //β¦
+ }
+});
diff --git a/website/assets/styles/components/logo-carousel.component.less b/website/assets/styles/components/logo-carousel.component.less
new file mode 100644
index 0000000000..2e057bfc05
--- /dev/null
+++ b/website/assets/styles/components/logo-carousel.component.less
@@ -0,0 +1,66 @@
+
+/**
+ *
+ *
+ * App-wide styles for our ajax buttons.
+ */
+
+[parasails-component='logo-carousel'] {
+ margin-bottom: 80px;
+ max-width: 1200px;
+ padding-left: 0px;
+ padding-right: 0px;
+ width: 100%;
+ [purpose='logo-carousel'] {
+ justify-content: center;
+ display: flex;
+ align-items: center;
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+ [purpose='logo-row'] {
+ white-space: nowrap;
+ animation: scroll-horizontal 80s linear infinite;
+ }
+ img {
+ vertical-align: middle;
+ height: 32px;
+ margin-right: 64px;
+ }
+ [purpose='fade-left'] {
+ height: 32px;
+ width: 80px;
+ position: absolute;
+ left: 0px;
+ bottom: 0px;
+ animation: none;
+ background: linear-gradient(90deg, #FFF 0%, rgba(255, 255, 255, 0.00) 100%);
+ }
+ [purpose='fade-right'] {
+ height: 32px;
+ width: 80px;
+ position: absolute;
+ right: 0px;
+ bottom: 0px;
+ animation: none;
+ background: linear-gradient(90deg, rgba(255, 255, 255, 0.00) 0%, #FFF 100%);
+ }
+ }
+
+ @media (max-width: 575px) {
+ margin-bottom: 64px;
+ [purpose='logo-carousel'] {
+ img {
+ margin-right: 48px;
+ }
+ }
+ }
+ @keyframes scroll-horizontal {
+ 0% {
+ transform: translateX(50%);
+ }
+ 100% {
+ transform: translateX(-50%);
+ }
+ }
+}
diff --git a/website/assets/styles/importer.less b/website/assets/styles/importer.less
index 0d2f94d678..e6b2c2829d 100644
--- a/website/assets/styles/importer.less
+++ b/website/assets/styles/importer.less
@@ -26,6 +26,7 @@
@import 'components/call-to-action.component.less';
@import 'components/scrollable-tweets.component.less';
@import 'components/parallax-city.component.less';
+@import 'components/logo-carousel.component.less';
// Per-page styles
@import 'pages/homepage.less';
diff --git a/website/assets/styles/pages/entrance/login.less b/website/assets/styles/pages/entrance/login.less
index cdf78c01d0..f49be521f6 100644
--- a/website/assets/styles/pages/entrance/login.less
+++ b/website/assets/styles/pages/entrance/login.less
@@ -9,6 +9,8 @@
a {
color: @core-fleet-black-75;
text-decoration: underline;
+ text-underline-offset: 2px;
+ line-height: 150%;
}
[purpose='customer-login-container'] {
max-width: 560px;
@@ -23,12 +25,24 @@
padding-left: 30px;
padding-right: 30px;
text-align: center;
+ margin-bottom: 40px;
+ }
+ [purpose='register-link'] {
+ margin-bottom: 8px;
+ a {
+ float: right;
+ color: @core-fleet-black-75;
+ text-decoration: underline;
+ font-size: 14px;
+ }
}
[purpose='customer-portal-form'] {
max-width: 560px;
border-radius: 16px;
- padding: 30px;
+ margin-bottom: 40px;
+ padding: 20px 32px 32px 32px;
label {
+ color: @core-fleet-black;
font-weight: 700;
margin-bottom: 4px;
}
@@ -62,27 +76,6 @@
}
}
- [purpose='features-list'] {
-
- word-wrap: overflow;
- padding-left: 40px;
- font-size: 14px;
- ul {
- list-style-type: none;
- padding-inline-start: 0px;
- }
- li {
- padding-bottom: 12px;
- color: @core-fleet-black-75;
- }
- img {
- display: inline;
- height: 16px;
- margin-right: 8px;
- }
-
- }
-
@media (max-width: 768px) {
padding-top: 60px;
[purpose='customer-portal-form'] {
diff --git a/website/assets/styles/pages/entrance/signup.less b/website/assets/styles/pages/entrance/signup.less
index 6288210bb1..6c9a3b2c78 100644
--- a/website/assets/styles/pages/entrance/signup.less
+++ b/website/assets/styles/pages/entrance/signup.less
@@ -7,17 +7,31 @@
a {
color: @core-fleet-black-75;
text-decoration: underline;
+ text-underline-offset: 2px;
}
[purpose='page-heading'] {
padding-left: 30px;
padding-right: 30px;
+ text-align: center;
+ margin-bottom: 40px;
}
+ [purpose='login-link'] {
+ margin-bottom: 4px;
+ a {
+ float: right;
+ color: @core-fleet-black-75;
+ text-decoration: underline;
+ font-size: 14px;
+ }
+ }
[purpose='customer-portal-form'] {
max-width: 560px;
border-radius: 16px;
- padding: 30px;
+ margin-bottom: 40px;
+ padding: 20px 32px 32px 32px;
label {
+ color: @core-fleet-black;
font-weight: 700;
margin-bottom: 4px;
}
@@ -25,9 +39,6 @@
height: 40px;
border-radius: 6px;
}
- .card-body {
- padding: 2em;
- }
.selectbox {
position: relative;
@@ -69,26 +80,6 @@
}
}
- [purpose='features-list'] {
- padding-left: 40px;
- font-size: 14px;
- word-wrap: overflow;
- ul {
- list-style-type: none;
- padding-inline-start: 0px;
- }
- li {
- padding-bottom: 12px;
- color: @core-fleet-black-75;
- white-space: nowrap;
- }
- img {
- display: inline;
- height: 16px;
- margin-right: 8px;
- }
-
- }
@media (max-width: 768px) {
padding-top: 60px;
diff --git a/website/assets/styles/pages/homepage.less b/website/assets/styles/pages/homepage.less
index 80fbb8029d..a9d8427354 100644
--- a/website/assets/styles/pages/homepage.less
+++ b/website/assets/styles/pages/homepage.less
@@ -68,57 +68,11 @@
}
[purpose='hero-logos'] {
- margin-bottom: 80px;
max-width: 1200px;
padding-left: 60px;
padding-right: 60px;
- overflow-x: hidden;
- width: 100%;
}
- [purpose='logo-carousel'] {
- display: flex;
- justify-content: space-around;
- align-items: center;
- position: relative;
- width: 100%;
- overflow: hidden;
- [purpose='logo-row'] {
- white-space: nowrap;
- animation: scroll-horizontal 80s linear infinite;
- }
- img {
- vertical-align: middle;
- height: 32px;
- margin-right: 64px;
- }
- [purpose='fade-left'] {
- height: 32px;
- width: 80px;
- position: absolute;
- left: 0px;
- bottom: 0px;
- animation: none;
- background: linear-gradient(90deg, #FFF 0%, rgba(255, 255, 255, 0.00) 100%);
- }
- [purpose='fade-right'] {
- height: 32px;
- width: 80px;
- position: absolute;
- right: 0px;
- bottom: 0px;
- animation: none;
- background: linear-gradient(90deg, rgba(255, 255, 255, 0.00) 0%, #FFF 100%);
- }
- }
- @keyframes scroll-horizontal {
- 0% {
- transform: translateX(-25%);
- }
- 100% {
- transform: translateX(-125%);
- }
- }
[purpose='homepage-content'] {
max-width: 1200px;
@@ -1143,26 +1097,6 @@
font-size: 16px;
}
}
- [purpose='hero-logos'] {
- [purpose='wayfair-logo'] {
- margin-right: 0px;
- }
- [purpose='uber-logo'] {
- margin-left: 0px;
- margin-right: auto;
- }
- [purpose='atlassian-logo'] {
- margin-left: auto;
- margin-right: 0px;
- }
- [purpose='fastly-logo'] {
- margin-left: auto;
- margin-right: auto;
- }
- [purpose='gusto-logo'] {
- margin-left: 0px;
- }
- }
[purpose='platform-block'] {
margin-bottom: 100px;
}
@@ -1285,11 +1219,6 @@
padding-left: 20px;
padding-right: 20px;
}
- [purpose='logo-carousel'] {
- img {
- margin-right: 48px;
- }
- }
[purpose='video-modal'] {
[purpose='modal-content'] {
width: 95vw;
@@ -1387,11 +1316,6 @@
padding-right: 20px;
padding-left: 20px;
}
- [purpose='hero-logos'] {
- img {
- display: inline;
- }
- }
[purpose='platform-block'] {
margin-bottom: 80px;
}
diff --git a/website/assets/styles/pages/start.less b/website/assets/styles/pages/start.less
index b2cdbc4a16..2ab70735ef 100644
--- a/website/assets/styles/pages/start.less
+++ b/website/assets/styles/pages/start.less
@@ -8,10 +8,16 @@
font-weight: 800;
line-height: 150%;
}
+ [purpose='logo-container'] {
+ max-width: 524px;
+ margin-left: auto;
+ margin-right: auto;
+ }
[purpose='page-container'] {
padding-top: 80px;
padding-left: 64px;
padding-right: 64px;
+ max-width: unset;
display: flex;
flex-direction: column;
}
@@ -67,6 +73,7 @@
padding-top: 60px;
padding-left: 40px;
padding-right: 40px;
+ max-width: 600px;
}
}
@@ -79,9 +86,11 @@
}
@media (max-width: 575px) {
+ [purpose='logo-container'] {
+ max-width: 100%;
+ }
[purpose='start-cards'] {
flex-direction: column;
- padding-bottom: 120px;
}
[purpose='card']:first-of-type {
margin-right: unset;
diff --git a/website/views/layouts/layout.ejs b/website/views/layouts/layout.ejs
index b2b4f62e82..6ec8255421 100644
--- a/website/views/layouts/layout.ejs
+++ b/website/views/layouts/layout.ejs
@@ -479,6 +479,7 @@
+
diff --git a/website/views/pages/entrance/login.ejs b/website/views/pages/entrance/login.ejs
index 0f38e452bc..a5b15cfca4 100644
--- a/website/views/pages/entrance/login.ejs
+++ b/website/views/pages/entrance/login.ejs
@@ -2,17 +2,19 @@
Welcome to Fleet
-
We just need a few details in order to get started.
+
We just need a few details in order to get started.
Welcome to Fleet
-
Sign in to your Fleet account.
+
Sign in to your Fleet account.
-
<%- /* Expose locals as `window.SAILS_LOCALS` :: */ exposeLocalsToBrowser() %>
diff --git a/website/views/pages/entrance/signup.ejs b/website/views/pages/entrance/signup.ejs
index af992bc0c9..eb7ef5bec5 100644
--- a/website/views/pages/entrance/signup.ejs
+++ b/website/views/pages/entrance/signup.ejs
@@ -1,14 +1,16 @@
-
Welcome to Fleet
-
We just need a few details in order to get started.
+
Welcome to Fleet
+
We just need a few details in order to get started.
+
@@ -67,7 +69,7 @@
Try again
-
+
<%- /* Expose locals as `window.SAILS_LOCALS` :: */ exposeLocalsToBrowser() %>
diff --git a/website/views/pages/homepage.ejs b/website/views/pages/homepage.ejs
index 91db1122b6..5087db21ee 100644
--- a/website/views/pages/homepage.ejs
+++ b/website/views/pages/homepage.ejs
@@ -19,70 +19,8 @@
<%/* Row of logos */%>
-
-
-
-
-

-

-

-

-

-

-

-

-

-

-

-
-

-

-

-
-

-
-
-

-

-

-

-

-

-

-

-

-

-

-
-

-

-

-
-

-
-
-

-

-

-

-

-

-

-

-

-

-

-
-

-

-

-
-

-
-
-
-
-
+
+
<%/* Homepage content */%>
diff --git a/website/views/pages/start.ejs b/website/views/pages/start.ejs
index ecab17ca57..e48d94933c 100644
--- a/website/views/pages/start.ejs
+++ b/website/views/pages/start.ejs
@@ -16,6 +16,9 @@
Purchase a Fleet Premium license
+
+
+
<%- /* Expose server-rendered data as window.SAILS_LOCALS :: */ exposeLocalsToBrowser() %>
From 65edee431d2dcf49adab6b459f4fd199322ef7f8 Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 20:09:30 -0500
Subject: [PATCH 13/64] Make Sam maintainer of open-positions.yml (#17921)
---
website/config/custom.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/website/config/custom.js b/website/config/custom.js
index c76c7568d1..5e021287fc 100644
--- a/website/config/custom.js
+++ b/website/config/custom.js
@@ -244,6 +244,7 @@ module.exports.custom = {
'handbook/README.md': 'mikermcneil', // See https://github.com/fleetdm/fleet/pull/13195
'handbook/company': 'mikermcneil',
'handbook/company/product-groups.md': ['lukeheath', 'sampfluger88','mikermcneil'],
+ 'handbook/company/open-positions.yml': ['@sampfluger88','mikermcneil'],
'handbook/digital-experience': ['sampfluger88','mikermcneil'],
'handbook/business-operations': ['sampfluger88','mikermcneil'],
'handbook/engineering': ['sampfluger88','mikermcneil', 'lukeheath'],
@@ -251,7 +252,6 @@ module.exports.custom = {
'handbook/sales': ['sampfluger88','mikermcneil'],
'handbook/demand': ['sampfluger88','mikermcneil'],
'handbook/customer-success': ['sampfluger88','mikermcneil'],
-
'/handbook/company/testimonials.yml': ['eashaw', 'mike-j-thomas', 'sampfluger88', 'mikermcneil'],
// GitHub issue templates
From 6331cbc468f7596ae4e248bb44034180a0403d9c Mon Sep 17 00:00:00 2001
From: Sam Pfluger <108141731+Sampfluger88@users.noreply.github.com>
Date: Wed, 27 Mar 2024 20:52:17 -0500
Subject: [PATCH 14/64] Fix broken links on app sec page (#17922)
---
.../business-operations/Application-security.md | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/handbook/business-operations/Application-security.md b/handbook/business-operations/Application-security.md
index 14b0553b2a..e914e99f0f 100644
--- a/handbook/business-operations/Application-security.md
+++ b/handbook/business-operations/Application-security.md
@@ -1,13 +1,13 @@
# Application security
-- [Describe your secure coding practices (SDLC)](#describe-your-secure-coding-practices-including-code-reviews-use-of-staticdynamic-security-testing-tools-3rd-party-scansreviews)
-- [SQL injection](#sql-injection)
-- [Broken authentication](#broken-authentication--authentication-session-management-flaws-that-compromise-passwords-keys-session-tokens-etc)
- - [Passwords](#passwords)
- - [Authentication tokens](#authentication-tokens)
-- [Sensitive data exposure](#sensitive-data-exposure--encryption-in-transit-at-rest-improperly-implemented-APIs)
-- [Cross-site scripting](#cross-site-scripting--ensure-an-attacker-cant-execute-scripts-in-the-users-browser)
-- [Components with known vulnerabilities](#components-with-known-vulnerabilities--prevent-the-use-of-libraries-frameworks-other-software-with-existing-vulnerabilities)
+- [Describe your secure coding practices (SDLC)](https://fleetdm.com/handbook/business-operations/application-security#describe-your-secure-coding-practices-including-code-reviews-use-of-static-dynamic-security-testing-tools-3-rd-party-scans-reviews)
+- [SQL injection](https://fleetdm.com/handbook/business-operations/application-security#sql-injection)
+- [Broken authentication](https://fleetdm.com/handbook/business-operations/application-security#broken-authentication-authentication-session-management-flaws-that-compromise-passwords-keys-session-tokens-etc)
+ - [Passwords](https://fleetdm.com/handbook/business-operations/application-security#passwords)
+ - [Authentication tokens](https://fleetdm.com/handbook/business-operations/application-security#authentication-tokens)
+- [Sensitive data exposure](https://fleetdm.com/handbook/business-operations/application-security#sensitive-data-exposure-encryption-in-transit-at-rest-improperly-implemented-apis)
+- [Cross-site scripting](https://fleetdm.com/handbook/business-operations/application-security#cross-site-scripting-ensure-an-attacker-cant-execute-scripts-in-the-users-browser)
+- [Components with known vulnerabilities](https://fleetdm.com/handbook/business-operations/application-security#components-with-known-vulnerabilities-prevent-the-use-of-libraries-frameworks-other-software-with-existing-vulnerabilities)
The Fleet community follows best practices when coding. Here are some of the ways we mitigate against the OWASP top 10 issues:
From fc19b0fa5f5524ee5aa66fc3a039b263fb94acab Mon Sep 17 00:00:00 2001
From: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Date: Wed, 27 Mar 2024 23:11:34 -0400
Subject: [PATCH 15/64] Update pricing-features-table.yml (#17845)
- [Policy
automations](https://fleetdm.com/docs/using-fleet/automations#policy-automations)
are free ...
---
handbook/company/pricing-features-table.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/handbook/company/pricing-features-table.yml b/handbook/company/pricing-features-table.yml
index 4fe0279bcd..a6d0363bd2 100644
--- a/handbook/company/pricing-features-table.yml
+++ b/handbook/company/pricing-features-table.yml
@@ -756,11 +756,11 @@
waysToUse:
- description: Automatically set admin access to Fleet based on your IDP
- industryName: Trigger a workflow based on a failing policy
- documentationUrl: https://fleetdm.com/docs/using-fleet/automations#automations
+ documentationUrl: https://fleetdm.com/docs/using-fleet/automations#policy-automations
productCategories: [Endpoint operations,Device management]
pricingTableCategories: [Integrations]
usualDepartment: IT
- tier: Premium
+ tier: Free
- industryName: Role-based access control
documentationUrl: https://fleetdm.com/docs/using-fleet/manage-access#manage-access
productCategories: [Endpoint operations,Device management,Vulnerability management]
From 2a8d84a0fe9f4c6a7853b49215eee58f9afc666e Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Thu, 28 Mar 2024 08:57:41 -0400
Subject: [PATCH 16/64] [tiny unreleased bugs] Fleet UI: Calendar feature
calendar settings page (#17905)
---
.../IntegrationsPage/cards/Calendars/Calendars.tsx | 12 ++++++------
.../IntegrationsPage/cards/Calendars/_styles.scss | 5 +++++
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx b/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx
index e9f6ed57c9..019d5f192e 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx
+++ b/frontend/pages/admin/IntegrationsPage/cards/Calendars/Calendars.tsx
@@ -27,7 +27,7 @@ const GOOGLE_WORKSPACE_DOMAINS =
const DOMAIN_WIDE_DELEGATION =
"https://www.fleetdm.com/learn-more-about/domain-wide-delegation";
const ENABLING_CALENDAR_API =
- "fleetdm.com/learn-more-about/enabling-calendar-api";
+ "https://www.fleetdm.com/learn-more-about/enabling-calendar-api";
const OAUTH_SCOPES =
"https://www.googleapis.com/auth/calendar.events,https://www.googleapis.com/auth/calendar.settings.readonly";
@@ -112,10 +112,10 @@ const Calendars = (): JSX.Element => {
// Must set all keys or no keys at all
if (!curFormData.apiKeyJson && !!curFormData.domain) {
- errors.apiKeyJson = "API key JSON must be present";
+ errors.apiKeyJson = "API key JSON must be completed";
}
if (!curFormData.domain && !!curFormData.apiKeyJson) {
- errors.domain = "Domain must be present";
+ errors.domain = "Domain must be completed";
}
if (curFormData.apiKeyJson) {
try {
@@ -167,11 +167,11 @@ const Calendars = (): JSX.Element => {
await configAPI.update({ integrations: destination });
renderFlash(
"success",
- "Successfully saved calendar integration settings"
+ "Successfully saved calendar integration settings."
);
refetchConfig();
} catch (e) {
- renderFlash("error", "Could not save calendar integration settings");
+ renderFlash("error", "Could not save calendar integration settings.");
} finally {
setIsUpdatingSettings(false);
}
@@ -286,7 +286,7 @@ const Calendars = (): JSX.Element => {
5. Configure your service account integration in Fleet using the
- form below:
+ form below.
-
Paste the full contents of the JSON file downloaded when
diff --git a/frontend/pages/admin/IntegrationsPage/cards/Calendars/_styles.scss b/frontend/pages/admin/IntegrationsPage/cards/Calendars/_styles.scss
index ffd30992ef..a3b2b7a8b7 100644
--- a/frontend/pages/admin/IntegrationsPage/cards/Calendars/_styles.scss
+++ b/frontend/pages/admin/IntegrationsPage/cards/Calendars/_styles.scss
@@ -12,6 +12,10 @@
margin-block-start: $pad-small;
}
+ ul {
+ margin: 0;
+ }
+
li {
margin: $pad-small 0;
}
@@ -27,6 +31,7 @@
}
&__api-key-json {
+ font-family: "SourceCodePro", $monospace;
min-width: 100%; // resize vertically only
height: 294px;
font-size: $x-small;
From 86071554e577c8317d59bad0461577a788586659 Mon Sep 17 00:00:00 2001
From: Patricia Ambrus <140438271+ambrusps@users.noreply.github.com>
Date: Thu, 28 Mar 2024 10:07:59 -0700
Subject: [PATCH 17/64] Update vendor-questionnaires.md - fix typo (#17917)
Typo - "primarily" was spelled wrong (1st question under data security
section)
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [ ] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.
- [ ] Added/updated tests
- [ ] If database migrations are included, checked table schema to
confirm autoupdate
- For database migrations:
- [ ] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ ] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
...
---
handbook/business-operations/vendor-questionnaires.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/handbook/business-operations/vendor-questionnaires.md b/handbook/business-operations/vendor-questionnaires.md
index 794f023997..a306ef2b75 100644
--- a/handbook/business-operations/vendor-questionnaires.md
+++ b/handbook/business-operations/vendor-questionnaires.md
@@ -20,7 +20,7 @@ Please also see [Application security](https://fleetdm.com/docs/using-fleet/appl
Please also see ["Data security"](https://fleetdm.com/handbook/business-operations/security-policies#data-management-policy)
| Question | Answer |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Should the need arise during an active relationship, how can our Data be removed from the Fleet's environment? | Customer data is primarially stored in RDS, S3, and Cloudwatch logs. Deleting these resources will remove the vast majority of customer data. Fleet can take further steps to remove data on demand, including deleting individual records in monitoring systems if requested. |
+| Should the need arise during an active relationship, how can our Data be removed from the Fleet's environment? | Customer data is primarily stored in RDS, S3, and Cloudwatch logs. Deleting these resources will remove the vast majority of customer data. Fleet can take further steps to remove data on demand, including deleting individual records in monitoring systems if requested. |
| Does Fleet support secure deletion (e.g., degaussing/cryptographic wiping) of archived and backed-up data as determined by the tenant? | Since all data is encrypted at rest, Fleet's secure deletion practice is to delete the encryption key. Fleet does not host customer services on-premise, so hardware specific deletion methods (such as degaussing) do not apply. |
| Does Fleet have a Data Loss Prevention (DLP) solution or compensating controls established to mitigate the risk of data leakage? | In addition to data controls enforced by Google Workspace on corporate endpoints, Fleet applies appropiate security controls for data depending on the requirements of the data, including but not limited to minimum access requirements. |
| Can your organization provide a certificate of data destruction if required? | No, physical media related to a certificate of data destruction is managed by AWS. Media storage devices used to store customer data are classified by AWS as critical and treated accordingly, as high impact, throughout their life-cycles. AWS has exacting standards on how to install, service, and eventually destroy the devices when they are no longer useful. When a storage device has reached the end of its useful life, AWS decommissions media using techniques detailed in NIST 800-88. Media that stored customer data is not removed from AWS control until it has been securely decommissioned. |
From 22387ba8a4035cad08ba68a267e3e57bea116edf Mon Sep 17 00:00:00 2001
From: Patricia Ambrus <140438271+ambrusps@users.noreply.github.com>
Date: Thu, 28 Mar 2024 10:08:38 -0700
Subject: [PATCH 18/64] typo fix - Update vendor-questionnaires.md (#17919)
"appropriate" was spelled wrong in the encryption section
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [ ] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for
new osquery data ingestion features.
- [ ] Added/updated tests
- [ ] If database migrations are included, checked table schema to
confirm autoupdate
- For database migrations:
- [ ] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ ] Manual QA for all new/changed functionality
- For Orbit and Fleet Desktop changes:
- [ ] Manual QA must be performed in the three main OSs, macOS, Windows
and Linux.
- [ ] Auto-update manual QA, from released version of component to new
version (see [tools/tuf/test](../tools/tuf/test/README.md)).
...
---
handbook/business-operations/vendor-questionnaires.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/handbook/business-operations/vendor-questionnaires.md b/handbook/business-operations/vendor-questionnaires.md
index a306ef2b75..9ed0b29943 100644
--- a/handbook/business-operations/vendor-questionnaires.md
+++ b/handbook/business-operations/vendor-questionnaires.md
@@ -38,7 +38,7 @@ Please also see ["Data security"](https://fleetdm.com/handbook/business-operatio
Please also see [Encryption and key management](https://fleetdm.com/handbook/business-operations/security-policies#encryption-policy)
| Question | Answer |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Does Fleet have a cryptographic key management process (generation, exchange, storage, safeguards, use, vetting, and replacement), that is documented and currently implemented, for all system components? (e.g. database, system, web, etc.) | All data is encrypted at rest using methods appropiate for the system (ie KMS for AWS based resources). Data going over the internet is encrypted using TLS or other appropiate transport security. |
+| Does Fleet have a cryptographic key management process (generation, exchange, storage, safeguards, use, vetting, and replacement), that is documented and currently implemented, for all system components? (e.g. database, system, web, etc.) | All data is encrypted at rest using methods appropriate for the system (ie KMS for AWS based resources). Data going over the internet is encrypted using TLS or other appropiate transport security. |
| Does Fleet allow customers to bring and their own encryption keys? | By default, Fleet does not allow for this, but if absolutely required, Fleet can accommodate this request. |
| Does Fleet have policy regarding key rotation ? Does rotation happens after every fixed time period or only when there is evidence of key leak ? | TLS certificates are managed by AWS Certificate Manager and are rotated automatically annually. |
From d984de41e70eabd589cc18117f2b81f679349ddc Mon Sep 17 00:00:00 2001
From: Tim Lee
Date: Thu, 28 Mar 2024 11:39:27 -0600
Subject: [PATCH 19/64] Add batch gitops processing for policies and queries
(#17714)
---
changes/17264-batch-process-gitops | 1 +
server/service/client.go | 64 ++++++++++++++++++++++++------
2 files changed, 52 insertions(+), 13 deletions(-)
create mode 100644 changes/17264-batch-process-gitops
diff --git a/changes/17264-batch-process-gitops b/changes/17264-batch-process-gitops
new file mode 100644
index 0000000000..cfa7ce9776
--- /dev/null
+++ b/changes/17264-batch-process-gitops
@@ -0,0 +1 @@
+- `fleetctl gitops` now batch processes queries and policies
\ No newline at end of file
diff --git a/server/service/client.go b/server/service/client.go
index 2bb5042235..659c4bfffe 100644
--- a/server/service/client.go
+++ b/server/service/client.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "golang.org/x/text/unicode/norm"
"io"
"net/http"
"os"
@@ -14,6 +13,8 @@ import (
"strings"
"time"
+ "golang.org/x/text/unicode/norm"
+
"github.com/fleetdm/fleet/v4/pkg/optjson"
"github.com/fleetdm/fleet/v4/pkg/spec"
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
@@ -22,6 +23,8 @@ import (
kithttp "github.com/go-kit/kit/transport/http"
)
+const batchSize = 100
+
// Client is used to consume Fleet APIs from Go code
type Client struct {
*baseClient
@@ -1099,11 +1102,19 @@ func (c *Client) doGitOpsPolicies(config *spec.GitOps, logFn func(format string,
numPolicies := len(config.Policies)
logFn("[+] syncing %d policies\n", numPolicies)
if !dryRun {
- // Note: We are reusing the spec flow here for adding/updating policies, instead of creating a new flow for GitOps.
- if err := c.ApplyPolicies(config.Policies); err != nil {
- return fmt.Errorf("error applying policies: %w", err)
+ totalApplied := 0
+ for i := 0; i < len(config.Policies); i += batchSize {
+ end := i + batchSize
+ if end > len(config.Policies) {
+ end = len(config.Policies)
+ }
+ totalApplied += end - i
+ // Note: We are reusing the spec flow here for adding/updating policies, instead of creating a new flow for GitOps.
+ if err := c.ApplyPolicies(config.Policies[i:end]); err != nil {
+ return fmt.Errorf("error applying policies: %w", err)
+ }
+ logFn("[+] synced %d policies\n", totalApplied)
}
- logFn("[+] synced %d policies\n", numPolicies)
}
}
var policiesToDelete []uint
@@ -1123,8 +1134,17 @@ func (c *Client) doGitOpsPolicies(config *spec.GitOps, logFn func(format string,
if len(policiesToDelete) > 0 {
logFn("[-] deleting %d policies\n", len(policiesToDelete))
if !dryRun {
- if err := c.DeletePolicies(config.TeamID, policiesToDelete); err != nil {
- return fmt.Errorf("error deleting policies: %w", err)
+ totalDeleted := 0
+ for i := 0; i < len(policiesToDelete); i += batchSize {
+ end := i + batchSize
+ if end > len(policiesToDelete) {
+ end = len(policiesToDelete)
+ }
+ totalDeleted += end - i
+ if err := c.DeletePolicies(config.TeamID, policiesToDelete[i:end]); err != nil {
+ return fmt.Errorf("error deleting policies: %w", err)
+ }
+ logFn("[-] deleted %d policies\n", totalDeleted)
}
}
}
@@ -1132,6 +1152,7 @@ func (c *Client) doGitOpsPolicies(config *spec.GitOps, logFn func(format string,
}
func (c *Client) doGitOpsQueries(config *spec.GitOps, logFn func(format string, args ...interface{}), dryRun bool) error {
+ batchSize := 100
// Get the ids and names of current queries to figure out which ones to delete
queries, err := c.GetQueries(config.TeamID, nil)
if err != nil {
@@ -1141,11 +1162,19 @@ func (c *Client) doGitOpsQueries(config *spec.GitOps, logFn func(format string,
numQueries := len(config.Queries)
logFn("[+] syncing %d queries\n", numQueries)
if !dryRun {
- // Note: We are reusing the spec flow here for adding/updating queries, instead of creating a new flow for GitOps.
- if err := c.ApplyQueries(config.Queries); err != nil {
- return fmt.Errorf("error applying queries: %w", err)
+ appliedCount := 0
+ for i := 0; i < len(config.Queries); i += batchSize {
+ end := i + batchSize
+ if end > len(config.Queries) {
+ end = len(config.Queries)
+ }
+ appliedCount += end - i
+ // Note: We are reusing the spec flow here for adding/updating queries, instead of creating a new flow for GitOps.
+ if err := c.ApplyQueries(config.Queries[i:end]); err != nil {
+ return fmt.Errorf("error applying queries: %w", err)
+ }
+ logFn("[+] synced %d queries\n", appliedCount)
}
- logFn("[+] synced %d queries\n", numQueries)
}
}
var queriesToDelete []uint
@@ -1165,8 +1194,17 @@ func (c *Client) doGitOpsQueries(config *spec.GitOps, logFn func(format string,
if len(queriesToDelete) > 0 {
logFn("[-] deleting %d queries\n", len(queriesToDelete))
if !dryRun {
- if err := c.DeleteQueries(queriesToDelete); err != nil {
- return fmt.Errorf("error deleting queries: %w", err)
+ deleteCount := 0
+ for i := 0; i < len(queriesToDelete); i += batchSize {
+ end := i + batchSize
+ if end > len(queriesToDelete) {
+ end = len(queriesToDelete)
+ }
+ deleteCount += end - i
+ if err := c.DeleteQueries(queriesToDelete[i:end]); err != nil {
+ return fmt.Errorf("error deleting queries: %w", err)
+ }
+ logFn("[-] deleted %d queries\n", deleteCount)
}
}
}
From 42c5bd5ca763a473565ed2791063aba3228673a1 Mon Sep 17 00:00:00 2001
From: Joanne Stableford <59930035+JoStableford@users.noreply.github.com>
Date: Thu, 28 Mar 2024 14:02:49 -0400
Subject: [PATCH 20/64] Updating security policies for formatting consistency
(#17936)
Updating to ensure alignment with the
[handbook](https://fleetdm.com/handbook/company/communications#lists),
and updating for consistency and readability. ...
---
.../business-operations/security-policies.md | 605 +++++++-----------
1 file changed, 225 insertions(+), 380 deletions(-)
diff --git a/handbook/business-operations/security-policies.md b/handbook/business-operations/security-policies.md
index cde44d2837..ce7302fae8 100644
--- a/handbook/business-operations/security-policies.md
+++ b/handbook/business-operations/security-policies.md
@@ -29,29 +29,29 @@ All Fleet employees and long-term collaborators are expected to read and electro
Fleet requires all team members to comply with the following acceptable use requirements and procedures:
-1. The use of Fleet computing systems is subject to monitoring by Fleet IT and/or Security teams.
+- The use of Fleet computing systems is subject to monitoring by Fleet IT and/or Security teams.
-2. Fleet team members must not leave computing devices (including laptops and smart devices) used for business purposes, including company-provided and BYOD devices, unattended in public. Unattended devices (even in private spaces) must be locked with the lid closed or through the OS screen lock mechanism.
+- Fleet team members must not leave computing devices (including laptops and smart devices) used for business purposes, including company-provided and BYOD devices, unattended in public. Unattended devices (even in private spaces) must be locked with the lid closed or through the OS screen lock mechanism.
-3. Device encryption must be enabled for all mobile devices accessing company data, such as whole-disk encryption for all laptops. This is automatically enforced on Fleet-managed macOS devices and must be manually configured for any unmanaged workstations.
+- Device encryption must be enabled for all mobile devices accessing company data, such as whole-disk encryption for all laptops. This is automatically enforced on Fleet-managed macOS devices and must be manually configured for any unmanaged workstations.
-4. Anti-malware or equivalent protection and monitoring must be installed and enabled on all endpoint systems that may be affected by malware, including workstations, laptops, and servers. This is automatically enforced on Fleet-managed macOS devices and must be manually configured for any unmanaged workstations.
+- Anti-malware or equivalent protection and monitoring must be installed and enabled on all endpoint systems that may be affected by malware, including workstations, laptops, and servers. This is automatically enforced on Fleet-managed macOS devices and must be manually configured for any unmanaged workstations.
-5. Teams must exclusively use legal software with a valid license installed through the "app store" or trusted sources. Well-documented open source software can be used. If in doubt, ask in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC).
+- Teams must exclusively use legal software with a valid license installed through the "app store" or trusted sources. Well-documented open source software can be used. If in doubt, ask in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC).
-6. Avoid sharing credentials. Secrets must be stored safely, using features such as GitHub secrets. For accounts and other sensitive data that need to be shared, use the company-provided password manager (1Password). If you don't know how to use the password manager or safely access secrets, please ask in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC)!
+- Avoid sharing credentials. Secrets must be stored safely, using features such as GitHub secrets. For accounts and other sensitive data that need to be shared, use the company-provided password manager (1Password). If you don't know how to use the password manager or safely access secrets, please ask in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC)!
-7. Sanitize and remove any sensitive or confidential information prior to posting. At Fleet, we are public by default. Sensitive information from logs, screenshots, or other types of data (eg. debug profiles) should not be shared publicly.
+- Sanitize and remove any sensitive or confidential information prior to posting. At Fleet, we are public by default. Sensitive information from logs, screenshots, or other types of data (eg. debug profiles) should not be shared publicly.
-8. Fleet team members must not let anyone else use Fleet-provided and managed workstations unsupervised, including family members and support personnel of vendors. Use screen sharing instead of allowing them to access your system directly, and never allow unattended screen sharing.
+- Fleet team members must not let anyone else use Fleet-provided and managed workstations unsupervised, including family members and support personnel of vendors. Use screen sharing instead of allowing them to access your system directly, and never allow unattended screen sharing.
-9. Device operating systems must be kept up to date. Fleet-managed macOS workstations will receive prompts for updates to be installed, and unmanaged devices are to be updated by the team member using them. Access may be revoked for devices not kept up to date.
+- Device operating systems must be kept up to date. Fleet-managed macOS workstations will receive prompts for updates to be installed, and unmanaged devices are to be updated by the team member using them. Access may be revoked for devices not kept up to date.
-10. Team members must not store sensitive data on external storage devices (USB sticks, external hard drives).
+- Team members must not store sensitive data on external storage devices (USB sticks, external hard drives).
-11. The use of Fleet company accounts on "shared" computers, such as hotel kiosk systems, is strictly prohibited.
+- The use of Fleet company accounts on "shared" computers, such as hotel kiosk systems, is strictly prohibited.
-12. Lost or stolen devices (laptops, or any other company-owned or personal devices used for work purposes) must be reported as soon as possible. Minutes count when responding to security incidents triggered by missing devices. Report a lost, stolen, or missing device by posting in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC), or use the security@ (fleetdm.com) email alias if you no longer have access to Slack. Include your name, the type of device, timeline (when were you last in control of the device?), whether the device was locked, whether any sensitive information is on the device, and any other relevant information in the report.
+- Lost or stolen devices (laptops, or any other company-owned or personal devices used for work purposes) must be reported as soon as possible. Minutes count when responding to security incidents triggered by missing devices. Report a lost, stolen, or missing device by posting in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC), or use the security@ (fleetdm.com) email alias if you no longer have access to Slack. Include your name, the type of device, timeline (when were you last in control of the device?), whether the device was locked, whether any sensitive information is on the device, and any other relevant information in the report.
When in doubt, **ASK!** (in [#g-security](https://fleetdm.slack.com/archives/C037Q8UJ0CC))
@@ -64,53 +64,53 @@ When in doubt, **ASK!** (in [#g-security](https://fleetdm.slack.com/archives/C03
Fleet requires all workforce members to comply with the following acceptable use requirements and procedures, such that:
-1. Access to all computing resources, including servers, end-user computing devices, network equipment, services, and applications, must be protected by strong authentication, authorization, and auditing.
+- Access to all computing resources, including servers, end-user computing devices, network equipment, services, and applications, must be protected by strong authentication, authorization, and auditing.
-2. Interactive user access to production systems must be associated with an account or login unique to each user.
+- Interactive user access to production systems must be associated with an account or login unique to each user.
-3. All credentials, including user passwords, service accounts, and access keys, must meet the length, complexity, age, and rotation requirements defined in Fleet security standards.
+- All credentials, including user passwords, service accounts, and access keys, must meet the length, complexity, age, and rotation requirements defined in Fleet security standards.
-4. Use a strong password and two-factor authentication (2FA) whenever possible to authenticate to all computing resources (including both devices and applications).
+- Use a strong password and two-factor authentication (2FA) whenever possible to authenticate to all computing resources (including both devices and applications).
-5. 2FA is required to access any critical system or resource, including but not limited to resources in Fleet production environments.
+- 2FA is required to access any critical system or resource, including but not limited to resources in Fleet production environments.
-6. Unused accounts, passwords, and access keys must be removed within 30 days.
+- Unused accounts, passwords, and access keys must be removed within 30 days.
-7. A unique access key or service account must be used for different applications or user access.
+- A unique access key or service account must be used for different applications or user access.
-8. Authenticated sessions must time out after a defined period of inactivity.
+- Authenticated sessions must time out after a defined period of inactivity.
### Access authorization and termination
Fleet policy requires that:
-1. Access authorization shall be implemented using role-based access control (RBAC) or a similar mechanism.
+- Access authorization shall be implemented using role-based access control (RBAC) or a similar mechanism.
-2. Standard access based on a user's job role may be pre-provisioned during employee onboarding. All subsequent access requests to computing resources must be approved by the requestorβs manager prior to granting and provisioning of access.
+- Standard access based on a user's job role may be pre-provisioned during employee onboarding. All subsequent access requests to computing resources must be approved by the requestorβs manager prior to granting and provisioning of access.
-3. Access to critical resources, such as production environments, must be approved by the security team in addition to the requestorβs manager.
+- Access to critical resources, such as production environments, must be approved by the security team in addition to the requestorβs manager.
-4. Access must be reviewed regularly and revoked if no longer needed.
+- Access must be reviewed regularly and revoked if no longer needed.
-5. Upon the termination of employment, all system access must be revoked, and user accounts terminated within 24-hours or one business day, whichever is shorter.
+- Upon the termination of employment, all system access must be revoked, and user accounts terminated within 24-hours or one business day, whichever is shorter.
-6. All system access must be reviewed at least annually and whenever a user's job role changes.
+- All system access must be reviewed at least annually and whenever a user's job role changes.
### Shared secrets management
Fleet policy requires that:
-1. Use of shared credentials/secrets must be minimized.
+- Use of shared credentials/secrets must be minimized.
-2. If required by business operations, secrets/credentials must be shared securely and stored in encrypted vaults that meet the Fleet data encryption standards.
+- If required by business operations, secrets/credentials must be shared securely and stored in encrypted vaults that meet the Fleet data encryption standards.
### Privileged access management
Fleet policy requires that:
-1. Automation with service accounts must be used to configure production systems when technically feasible.
+- Automation with service accounts must be used to configure production systems when technically feasible.
-2. Use of high privilege accounts must only be performed when absolutely necessary.
+- Use of high privilege accounts must only be performed when absolutely necessary.
## Asset management policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/)_
@@ -123,11 +123,11 @@ You can't protect what you can't see. Therefore, Fleet must maintain an accurate
Fleet policy requires that:
-1. IT and/or security must maintain an inventory of all critical company assets, both physical and logical.
+- IT and/or security must maintain an inventory of all critical company assets, both physical and logical.
-2. All assets should have identified owners and a risk/data classification tag.
+- All assets should have identified owners and a risk/data classification tag.
-3. All company-owned computer purchases must be tracked.
+- All company-owned computer purchases must be tracked.
## Business continuity and disaster recovery policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/)_
@@ -140,11 +140,11 @@ The Fleet business continuity and disaster recovery plan establishes procedures
Fleet policy requires that:
-1. A plan and process for business continuity and disaster recovery (BCDR), will be defined and documented including the backup and recovery of critical systems and data,.
+- A plan and process for business continuity and disaster recovery (BCDR), will be defined and documented including the backup and recovery of critical systems and data,.
-2. BCDR shall be simulated and tested at least once a year.
+- BCDR shall be simulated and tested at least once a year.
-3. Security controls and requirements will be maintained during all BCDR activities.
+- Security controls and requirements will be maintained during all BCDR activities.
### Business continuity plan
@@ -153,22 +153,22 @@ Fleet policy requires that:
The following order of succession to make sure that decision-making authority for the Fleet Contingency Plan is uninterrupted. The Chief Executive Officer (CEO) is responsible for ensuring the safety of personnel and the execution of procedures documented within this Fleet Contingency Plan. The CTO is responsible for the recovery of Fleet technical environments. If the CEO or Head of Engineering cannot function as the overall authority or choose to delegate this responsibility to a successor, the board of directors shall serve as that authority or choose an alternative delegate.
For technical incidents:
-1. CTO (Luke Heath)
-2. CEO (Mike McNeil)
+- CTO (Luke Heath)
+- CEO (Mike McNeil)
For business/operational incidents:
-1. CEO (Mike McNeil)
-2. Head of Business Operations (Joanne Stableford)
+- CEO (Mike McNeil)
+- Head of Business Operations (Joanne Stableford)
### Response Teams and Responsibilities
The following teams have been developed and trained to respond to a contingency event affecting Fleet infrastructure and systems.
-1. **Infrastructure** is responsible for recovering the Fleet automatic update service hosted environment. The team includes personnel responsible for the daily IT operations and maintenance. The team reports to the CTO.
+- **Infrastructure** is responsible for recovering the Fleet automatic update service hosted environment. The team includes personnel responsible for the daily IT operations and maintenance. The team reports to the CTO.
-2. **People Ops** is responsible for ensuring the physical safety of all Fleet personnel and coordinating the response to incidents that could impact it. Fleet has no physical site to recover. The team reports to the CEO.
+- **People Ops** is responsible for ensuring the physical safety of all Fleet personnel and coordinating the response to incidents that could impact it. Fleet has no physical site to recover. The team reports to the CEO.
-3. **Security** is responsible for assessing and responding to all cybersecurity-related incidents according to Fleet Incident Response policy and procedures. The security team shall assist the above teams in recovery as needed in non-cybersecurity events. The team leader is the CTO.
+- **Security** is responsible for assessing and responding to all cybersecurity-related incidents according to Fleet Incident Response policy and procedures. The security team shall assist the above teams in recovery as needed in non-cybersecurity events. The team leader is the CTO.
Members of the above teams must maintain local copies of the contact information of the BCDR succession team. Additionally, the team leads must maintain a local copy of this policy in the event Internet access is not available during a disaster scenario.
@@ -184,20 +184,18 @@ This phase addresses the initial actions taken to detect and assess the damage i
The notification sequence is listed below:
-* The first responder is to notify the CTO. All known information must be relayed.
-* The CTO is to contact the Response Teams and inform them of the event. The CTO or delegate is responsible to beginning the assessment procedures.
-* The CTO is to notify team members and direct them to complete the assessment procedures outlined below to determine the extent of the issue and estimated recovery time.
-* The Fleet Contingency Plan is to be activated if one or more of the following criteria are met:
-
- * Fleet automatic update service will be unavailable for more than 48 hours.
- * Cloud infrastructure service is damaged and will be unavailable for more than 24 hours.
- * Other criteria, as appropriate and as defined by Fleet.
-
-* If the plan is to be activated, the CTO is to notify and inform team members of the event details.
-* Upon notification from the CTO, group leaders and managers must notify their respective teams. Team members are to be informed of all applicable information and prepared to respond and relocate if necessary.
-* The CTO is to notify the remaining personnel and executive leadership on the general status of the incident.
-* Notification can be via Slack, email, or phone.
-* The CTO posts a blog post explaining that the service is down and recovery is in progress.
+1. The first responder is to notify the CTO. All known information must be relayed.
+2. The CTO is to contact the Response Teams and inform them of the event. The CTO or delegate is responsible to beginning the assessment procedures.
+3. The CTO is to notify team members and direct them to complete the assessment procedures outlined below to determine the extent of the issue and estimated recovery time.
+4. The Fleet Contingency Plan is to be activated if one or more of the following criteria are met:
+ - Fleet automatic update service will be unavailable for more than 48 hours.
+ - Cloud infrastructure service is damaged and will be unavailable for more than 24 hours.
+ - Other criteria, as appropriate and as defined by Fleet.
+5. If the plan is to be activated, the CTO is to notify and inform team members of the event details.
+6. Upon notification from the CTO, group leaders and managers must notify their respective teams. Team members are to be informed of all applicable information and prepared to respond and relocate if necessary.
+7. The CTO is to notify the remaining personnel and executive leadership on the general status of the incident.
+8. Notification can be via Slack, email, or phone.
+9. The CTO posts a blog post explaining that the service is down and recovery is in progress.
#### Reconstitution Phase
@@ -228,33 +226,22 @@ Additionally, this policy outlines requirements and procedures to create and mai
Data backup is an important part of the day-to-day operations of Fleet. To protect the confidentiality, integrity, and availability of sensitive and critical data, both for Fleet and Fleet Customers, complete backups are done daily to assure that data remains available when needed and in case of a disaster.
Fleet policy requires that:
-
-1. Data should be classified at the time of creation or acquisition.
-
-2. Fleet must maintain an up-to-date inventory and data flows mapping of all critical data.
-
-3. All business data should be stored or replicated to a company-controlled repository.
-
-4. Data must be backed up according to the level defined in Fleet data classification.
-
-5. Data backup must be validated for integrity.
-
-6. The data retention period must be defined and comply with any and all applicable regulatory and contractual requirements. More specifically,
-
- * Data and records belonging to Fleet platform customers must be retained
- per Fleet product terms and conditions and/or specific contractual
- agreements.
-
-7. By default, all security documentation and audit trails are kept for a minimum of seven years unless otherwise specified by Fleet data classification, specific regulations, or contractual agreement.
+- Data should be classified at the time of creation or acquisition.
+- Fleet must maintain an up-to-date inventory and data flows mapping of all critical data.
+- All business data should be stored or replicated to a company-controlled repository.
+- Data must be backed up according to the level defined in Fleet data classification.
+- Data backup must be validated for integrity.
+- The data retention period must be defined and comply with any and all applicable regulatory and contractual requirements. More specifically, **data and records belonging to Fleet platform customers must be retained per Fleet product terms and conditions and/or specific contractual agreements.**
+- By default, all security documentation and audit trails are kept for a minimum of seven years unless otherwise specified by Fleet data classification, specific regulations, or contractual agreement.
### Data Classification Model
Fleet defines the following four data classifications:
-* **Critical**
-* **Confidential**
-* **Internal**
-* **Public**
+- **Critical**
+- **Confidential**
+- **Internal**
+- **Public**
As Fleet is an open company by default, most of our data falls into **public**.
@@ -268,12 +255,12 @@ External disclosure of critical data is strictly prohibited without an approved
*Example Critical Data Types* include
-* PII (personal identifiable information)
-* ePHI (electronically protected health information)
-* Production security data, such as
+- PII (personal identifiable information)
+- ePHI (electronically protected health information)
+- Production security data, such as
- Production secrets, passwords, access keys, certificates, etc.
- Production security audit logs, events, and incident data
-* Production customer data
+- Production customer data
**Confidential** and proprietary data represents company secrets and is of significant value to the company.
@@ -284,14 +271,14 @@ Disclosure requires the signing of NDA and management approval.
*Example Confidential Data Types* include
-* Business plans
-* Employee/HR data
-* News and public announcements (pre-announcement)
-* Patents (pre-filing)
-* Production metadata (server logs, non-secret configurations, etc.)
-* Non-production security data, including
- - Non-prod secrets, passwords, access keys, certificates, etc.
- - Non-prod security audit logs, events, and incident data
+- Business plans
+- Employee/HR data
+- News and public announcements (pre-announcement)
+- Patents (pre-filing)
+- Production metadata (server logs, non-secret configurations, etc.)
+- Non-production security data, including
+ - Non-prod secrets, passwords, access keys, certificates, etc.
+ - Non-prod security audit logs, events, and incident data
**Internal** data contains information used for internal operations.
@@ -305,11 +292,11 @@ protected.
*Example Internal Data Types* include
-* Fleet source code.
-* news and public announcements (post-announcement).
-* marketing materials.
-* product documentation.
-* content posted on the company website(s) and social media channel(s).
+- Fleet source code.
+- news and public announcements (post-announcement).
+- marketing materials.
+- product documentation.
+- content posted on the company website(s) and social media channel(s).
#### Data Handling Requirements Matrix
@@ -345,17 +332,12 @@ This process is followed when offboarding a customer and deleting all of the pro
Fleet requires all workforce members to comply with the encryption policy, such that:
-1. The storage drives of all Fleet-owned workstations must be encrypted and enforced by the IT and/or security team.
-
-2. Confidential data must be stored in a manner that supports user access logs.
-
-3. All Production Data at rest is stored on encrypted volumes.
-
-4. Volume encryption keys and machines that generate volume encryption keys are protected from unauthorized access. Volume encryption key material is protected with access controls such that the key material is only accessible by privileged accounts.
-
-5. Encrypted volumes use strong cipher algorithms, key strength, and key management process as defined below.
-
-6. Data is protected in transit using recent TLS versions with ciphers recognized as secure.
+- The storage drives of all Fleet-owned workstations must be encrypted and enforced by the IT and/or security team.
+- Confidential data must be stored in a manner that supports user access logs.
+- All Production Data at rest is stored on encrypted volumes.
+- Volume encryption keys and machines that generate volume encryption keys are protected from unauthorized access. Volume encryption key material is protected with access controls such that the key material is only accessible by privileged accounts.
+- Encrypted volumes use strong cipher algorithms, key strength, and key management process as defined below.
+- Data is protected in transit using recent TLS versions with ciphers recognized as secure.
### Local disk/volume encryption
@@ -363,13 +345,11 @@ Encryption and key management for local disk encryption of end-user devices foll
### Protecting data in transit
-1. All external data transmission is encrypted end-to-end. This includes, but is not limited to, cloud infrastructure and third-party vendors and applications.
-
-2. Transmission encryption keys and systems that generate keys are protected from unauthorized access. Transmission encryption key materials are protected with access controls and may only be accessed by privileged accounts.
-
-3. TLS endpoints must score at least an "A" on SSLLabs.com.
-
-4. Transmission encryption keys are limited to use for one year and then must be regenerated.
+- All external data transmission is encrypted end-to-end. This includes, but is not limited to, cloud infrastructure and third-party vendors and applications.
+- Transmission encryption keys and systems that generate keys are protected from unauthorized access.
+- Transmission encryption key materials are protected with access controls and may only be accessed by privileged accounts.
+- TLS endpoints must score at least an "A" on SSLLabs.com.
+- Transmission encryption keys are limited to use for one year and then must be regenerated.
### Authorized Sub-Processors for Fleet Cloud services
@@ -391,95 +371,70 @@ Fleet policy requires all workforce members to comply with the HR Security Polic
Fleet policy requires that:
-1. Background verification checks on candidates for employees and contractors with production access to the Fleet infrastructure resources must be carried out in accordance with relevant laws, regulations, and ethics. These checks should be proportional to the business requirements, the classification of the information to be accessed, and the perceived risk.
-
-2. Employees, contractors, and third-party users must agree to and sign the terms and conditions of their employment contract and comply with acceptable use.
-
-3. Employees will perform an onboarding process that familiarizes them with the environments, systems, security requirements, and procedures that Fleet already has in place. Employees will also have ongoing security awareness training that is audited.
-
-4. Employee offboarding will include reiterating any duties and responsibilities still valid after terminations, verifying that access to any Fleet systems has been removed, and ensuring that all company-owned assets are returned.
-
-5. Fleet and its employees will take reasonable measures to make sure no sensitive data is transmitted via digital communications such as email or posted on social media outlets.
-
-6. Fleet will maintain a list of prohibited activities that will be part of onboarding procedures and have training available if/when the list of those activities changes.
-
-7. A fair disciplinary process will be used for employees suspected of committing security breaches. Fleet will consider multiple factors when deciding the response, such as whether or not this was a first offense, training, business contracts, etc. Fleet reserves the right to terminate employees in the case of severe cases of misconduct.
-
-8. Fleet will maintain a reporting structure that aligns with the organization's business lines and/or individual's functional roles. The list of employees and reporting structure must be available to [all employees](https://docs.google.com/spreadsheets/d/1OSLn-ZCbGSjPusHPiR5dwQhheH1K8-xqyZdsOe9y7qc/edit#gid=0).
-
-9. Employees will receive regular feedback and acknowledgment from their managers and peers. Managers will give constant feedback on performance, including but not limited to during regular one-on-one meetings.
-
-10. Fleet will publish job descriptions for available positions and conduct interviews to assess a candidate's technical skills as well as soft skills prior to hiring.
-
-11. Background checks of an employee or contractor must be performed by operations and/or the hiring team before we grant the new employee or contractor access to the Fleet production environment.
-
-12. A list of employees and contractors will be maintained, including their titles and managers, and made available to everyone internally.
-
-13. An [anonymous](https://docs.google.com/forms/d/e/1FAIpQLSdv2abLfCUUSxFCrSwh4Ou5yF80c4V2K_POoYbHt3EU1IY-sQ/viewform?vc=0&c=0&w=1&flr=0&fbzx=4276110450338060288) form to report unethical behavior will be provided to employees.
+- Background verification checks on candidates for employees and contractors with production access to the Fleet infrastructure resources must be carried out in accordance with relevant laws, regulations, and ethics. These checks should be proportional to the business requirements, the classification of the information to be accessed, and the perceived risk.
+- Employees, contractors, and third-party users must agree to and sign the terms and conditions of their employment contract and comply with acceptable use.
+- Employees will perform an onboarding process that familiarizes them with the environments, systems, security requirements, and procedures that Fleet already has in place. Employees will also have ongoing security awareness training that is audited.
+- Employee offboarding will include reiterating any duties and responsibilities still valid after terminations, verifying that access to any Fleet systems has been removed, and ensuring that all company-owned assets are returned.
+- Fleet and its employees will take reasonable measures to make sure no sensitive data is transmitted via digital communications such as email or posted on social media outlets.
+- Fleet will maintain a list of prohibited activities that will be part of onboarding procedures and have training available if/when the list of those activities changes.
+- A fair disciplinary process will be used for employees suspected of committing security breaches. Fleet will consider multiple factors when deciding the response, such as whether or not this was a first offense, training, business contracts, etc. Fleet reserves the right to terminate employees in the case of severe cases of misconduct.
+- Fleet will maintain a reporting structure that aligns with the organization's business lines and/or individual's functional roles. The list of employees and reporting structure must be available to [all employees](https://docs.google.com/spreadsheets/d/1OSLn-ZCbGSjPusHPiR5dwQhheH1K8-xqyZdsOe9y7qc/edit#gid=0).
+- Employees will receive regular feedback and acknowledgment from their managers and peers. Managers will give constant feedback on performance, including but not limited to during regular one-on-one meetings.
+- Fleet will publish job descriptions for available positions and conduct interviews to assess a candidate's technical skills as well as soft skills prior to hiring.
+- Background checks of an employee or contractor must be performed by operations and/or the hiring team before we grant the new employee or contractor access to the Fleet production environment.
+- A list of employees and contractors will be maintained, including their titles and managers, and made available to everyone internally.
+- An [anonymous](https://docs.google.com/forms/d/e/1FAIpQLSdv2abLfCUUSxFCrSwh4Ou5yF80c4V2K_POoYbHt3EU1IY-sQ/viewform?vc=0&c=0&w=1&flr=0&fbzx=4276110450338060288) form to report unethical behavior will be provided to employees.
## Incident response policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/). Based on the SANS incident response process._
Fleet policy requires that:
-1. All computing environments and systems must be monitored in accordance with Fleet policies and procedures specified in the Fleet handbook.
-2. Alerts must be reviewed to identify security incidents.
-3. Incident response procedures are invoked upon discovery of a valid security incident.
-4. Incident response team and management must comply with any additional requests by law enforcement in the event of a criminal investigation or national security, including but not limited to warranted data requests, subpoenas, and breach notifications.
+- All computing environments and systems must be monitored in accordance with Fleet policies and procedures specified in the Fleet handbook.
+- Alerts must be reviewed to identify security incidents.
+- Incident response procedures are invoked upon discovery of a valid security incident.
+- Incident response team and management must comply with any additional requests by law enforcement in the event of a criminal investigation or national security, including but not limited to warranted data requests, subpoenas, and breach notifications.
### Incident response plan
#### Security Incident Response Team (SIRT)
The Security Incident Response Team (SIRT) is responsible for
-* Reviewing analyzing, and logging all received reports and tracking their statuses.
-* Performing investigations, creating and executing action plans, and post-incident activities.
-* Collaboration with law enforcement agencies.
+- Reviewing analyzing, and logging all received reports and tracking their statuses.
+- Performing investigations, creating and executing action plans, and post-incident activities.
+- Collaboration with law enforcement agencies.
Current members of the Fleet SIRT:
-
-* CTO
-* CEO
-* VP of Customer Success
+- CTO
+- CEO
+- VP of Customer Success
#### Incident Management Process
Fleet's incident response classifies security-related events into the following categories:
+- **Events** - Any observable computer security-related occurrence in a system or network with a negative consequence. Examples:
+ - Hardware component failing, causing service outages.
+ - Software error causing service outages.
+ - General network or system instability.
-* **Events** - Any observable computer security-related occurrence in a system
- or network with a negative consequence. Examples:
+- **Precursors** - A sign that an incident may occur in the future. Examples:
+ - Monitoring system showing unusual behavior.
+ - Audit log alerts indicated several failed login attempts.
+ - Suspicious emails that target specific Fleet staff members with administrative access to production systems.
+ - Alerts raised from a security control source based on its monitoring policy, such as:
+ - Google Workspace (user authentication activities)
+ - Fleet (internal instance)
+ - Syslog events from servers
- * Hardware component failing, causing service outages.
- * Software error causing service outages.
- * General network or system instability.
+- **Indications** - A sign that an incident may have occurred or may be occurring at the present time. Examples:
+ - Alerts for modified system files or unusual system accesses.
+ - Antivirus alerts for infected files or devices.
+ - Excessive network traffic directed at unexpected geographic locations.
-* **Precursors** - A sign that an incident may occur in the future. Examples:
-
- * Monitoring system showing unusual behavior.
- * Audit log alerts indicated several failed login attempts.
- * Suspicious emails that target specific Fleet staff members with
- administrative access to production systems.
- * Alerts raised from a security control source based on its monitoring
- policy, such as
-
- - Google Workspace (user authentication activities)
- - Fleet (internal instance)
- - Syslog events from servers
-
-* **Indications** - A sign that an incident may have occurred or may be
- occurring at the present time. Examples:
-
- * Alerts for modified system files or unusual system accesses.
- * Antivirus alerts for infected files or devices.
- * Excessive network traffic directed at unexpected geographic locations.
-
-* **Incidents** - A confirmed attack/indicator of compromise or a validated
- violation of computer security policies or acceptable use policies, often
- resulting in data breaches. Examples:
-
- * Unauthorized disclosure of sensitive data
- * Unauthorized change or destruction of sensitive data
- * A data breach accomplished by an internal or external entity
- * A Denial-of-Service (DoS) attack causing a critical service to become
+- **Incidents** - A confirmed attack/indicator of compromise or a validated violation of computer security policies or acceptable use policies, often resulting in data breaches. Examples:
+ - Unauthorized disclosure of sensitive data
+ - Unauthorized change or destruction of sensitive data
+ - A data breach accomplished by an internal or external entity
+ - A Denial-of-Service (DoS) attack causing a critical service to become
unreachable
Fleet employees must report any unauthorized or suspicious activity seen on
@@ -492,52 +447,23 @@ Incidents of a severity/impact rating higher than **MINOR** shall trigger the re
#### I - Identification and Triage
-1. Immediately upon observation, Fleet members report suspected and known
- Events, Precursors, Indications, and Incidents in one of the following ways:
-
- 1. Direct report to management, CTO, CEO, or
- other
- 2. Email
- 3. Phone call
- 4. Slack
-
-2. The individual receiving the report facilitates the collection of additional
- information about the incident, as needed, and notifies the CTO
- (if not already done).
-
-3. The CTO determines if the issue is an Event, Precursor,
- Indication, or Incident.
-
- 1. If the issue is an event, indication, or precursor, the CTO
- forwards it to the appropriate resource for resolution.
-
- 1. Non-Technical Event (minor infringement): the CTO of the
- designee creates an appropriate issue in GitHub and further investigates
- the incident as needed.
- 2. Technical Event: Assign the issue to a technical resource for
- resolution. This resource may also be a contractor or outsourced
- technical resource in the event of a lack of resource or expertise in
- the area.
-
- 2. If the issue is a security incident, the CTO activates the
- Security Incident Response Team (SIRT) and notifies senior leadership by
- email.
-
- 1. If a non-technical security incident is discovered, the SIRT completes
- the investigation, implements preventative measures, and resolves the
- security incident.
- 2. Once the investigation is completed, progress to Phase V, Follow-up.
- 3. If the issue is a technical security incident, commence to Phase II:
- Containment.
- 4. The Containment, Eradication, and Recovery Phases are highly
- technical. It is important to have them completed by a highly
- qualified technical security resource with oversight by the SIRT team.
- 5. Each individual on the SIRT and the technical security resource
- document all measures taken during each phase, including the start and
- end times of all efforts.
- 6. The lead member of the SIRT team facilitates the initiation of an Incident
- ticket in GitHub Security Project and documents all findings and details
- in the ticket.
+1. Immediately upon observation, Fleet members report suspected and known Events, Precursors, Indications, and Incidents in one of the following ways:
+ - Direct report to management, CTO, CEO, or other
+ - Email
+ - Phone call
+ - Slack
+2. The individual receiving the report facilitates the collection of additional information about the incident, as needed, and notifies the CTO (if not already done).
+3. The CTO determines if the issue is an Event, Precursor, Indication, or Incident.
+ - If the issue is an event, indication, or precursor, the CTO forwards it to the appropriate resource for resolution.
+ - Non-Technical Event (minor infringement): the CTO of the designee creates an appropriate issue in GitHub and further investigates the incident as needed.
+ - Technical Event: Assign the issue to a technical resource for resolution. This resource may also be a contractor or outsourced technical resource in the event of a lack of resource or expertise in the area.
+ - If the issue is a security incident, the CTO activates the Security Incident Response Team (SIRT) and notifies senior leadership by email.
+ - If a non-technical security incident is discovered, the SIRT completes the investigation, implements preventative measures, and resolves the security incident.
+ - Once the investigation is completed, progress to Phase V, Follow-up.
+ - If the issue is a technical security incident, commence to Phase II: Containment.
+ - The Containment, Eradication, and Recovery Phases are highly technical. It is important to have them completed by a highly qualified technical security resource with oversight by the SIRT team.
+ - Each individual on the SIRT and the technical security resource document all measures taken during each phase, including the start and end times of all efforts.
+ - The lead member of the SIRT team facilitates the initiation of an Incident ticket in GitHub Security Project and documents all findings and details in the ticket.
* The intent of the Incident ticket is to provide a summary of all
events, efforts, and conclusions of each Phase of this policy and
@@ -577,27 +503,17 @@ appropriate.
2. Secure the blast radius (i.e., a physical or logical network perimeter or
access zone).
3. Perform the following forensic analysis preparation, as needed:
+ - Securely connect to the affected system over a trusted connection.
+ - Retrieve any volatile data from the affected system.
+ - Determine the relative integrity and the appropriateness of backing the system up.
+ - As necessary, take a snapshot of the disk image for further forensic, and if appropriate, back up the system.
+ - Change the password(s) to the affected system(s).
+ - Determine whether it is safe to continue operations with the affected system(s).
+ - If it is safe, allow the system to continue to functioning; and move to Phase V, Post Incident Analysis and Follow-up.
+ - If it is NOT safe to allow the system to continue operations, discontinue the system(s) operation and move to Phase III, Eradication.
+ - The individual completing this phase provides written communication to the SIRT.
- 1. Securely connect to the affected system over a trusted connection.
- 2. Retrieve any volatile data from the affected system.
- 3. Determine the relative integrity and the appropriateness of backing the
- system up.
- 4. As necessary, take a snapshot of the disk image for further forensic,
- and if appropriate, back up the system.
- 5. Change the password(s) to the affected system(s).
- 6. Determine whether it is safe to continue operations with the affected
- system(s).
- 7. If it is safe, allow the system to continue to functioning; and move to
- Phase V, Post Incident Analysis and Follow-up.
- 8. If it is NOT safe to allow the system to continue operations, discontinue
- the system(s) operation and move to Phase III, Eradication.
- 9. The individual completing this phase provides written communication to
- the SIRT.
-
-4. Complete any documentation relative to the security incident containment on the
- Incident ticket, using
- [SANS IH Containment Form](https://www.sans.org/media/score/incident-forms/IH-Containment.pdf)
- as a template.
+4. Complete any documentation relative to the security incident containment on the Incident ticket, using [SANS IH Containment Form](https://www.sans.org/media/score/incident-forms/IH-Containment.pdf) as a template.
5. Continuously apprise Senior Management of progress.
6. Continue to notify affected Customers and Partners with relevant updates as
needed.
@@ -611,28 +527,17 @@ resulting security exposures that are now on the affected system(s).
2. Strengthen the defenses surrounding the affected system(s), where possible (a
risk assessment may be needed and can be determined by the Head of Security).
This may include the following:
+ - An increase in network perimeter defenses.
+ - An increase in system monitoring defenses.
+ - Remediation ("fixing") any security issues within the affected system, such as removing unused services/general host hardening techniques.
- 1. An increase in network perimeter defenses.
- 2. An increase in system monitoring defenses.
- 3. Remediation ("fixing") any security issues within the affected system,
- such as removing unused services/general host hardening techniques.
+3. Conduct a detailed vulnerability assessment to verify all the holes/gaps that can be exploited are addressed.
+ - If additional issues or symptoms are identified, take appropriate preventative measures to eliminate or minimize potential future compromises.
-3. Conduct a detailed vulnerability assessment to verify all the holes/gaps that
- can be exploited are addressed.
-
- 1. If additional issues or symptoms are identified, take appropriate
- preventative measures to eliminate or minimize potential future
- compromises.
-
-4. Update the Incident ticket with Eradication details, using
- [SANS IH Eradication Form](https://www.sans.org/media/score/incident-forms/IH-Eradication.pdf)
- as a template.
-5. Update the documentation with the information learned from the vulnerability
- assessment, including the cause, symptoms, and the method used to fix the
- problem with the affected system(s).
+4. Update the Incident ticket with Eradication details, using [SANS IH Eradication Form](https://www.sans.org/media/score/incident-forms/IH-Eradication.pdf) as a template.
+5. Update the documentation with the information learned from the vulnerability assessment, including the cause, symptoms, and the method used to fix the problem with the affected system(s).
6. Apprise Senior Management of the progress.
-7. Continue to notify affected Customers and Partners with relevant updates as
- needed.
+7. Continue to notify affected Customers and Partners with relevant updates as needed.
8. Move to Phase IV, Recovery.
#### IV - Recovery (Technical)
@@ -641,26 +546,15 @@ The Recovery Phase represents the SIRT's effort to restore the affected
system(s) to operation after the resulting security exposures, if any, have
been corrected.
-1. The technical team determines if the affected system(s) have been changed in
- any way.
-
- 1. If they have, the technical team restores the system to its proper,
- intended functioning ("last known good").
- 2. Once restored, the team validates that the system functions the way it
- was intended/had functioned in the past. This may require the involvement
- of the business unit that owns the affected system(s).
- 3. If the operation of the system(s) had been interrupted (i.e., the system(s)
- had been taken offline or dropped from the network while triaged),
- restart the restored and validated system(s) and monitor for behavior.
- 4. If the system had not been changed in any way but was taken offline
- (i.e., operations had been interrupted), restart the system and monitor
- for proper behavior.
- 5. Update the documentation with the detail that was determined during this
- phase.
- 6. Apprise Senior Management of progress.
- 7. Continue to notify affected Customers and Partners with relevant updates
- as needed.
- 8. Move to Phase V, Follow-up.
+The technical team determines if the affected system(s) have been changed in any way.
+1. If they have, the technical team restores the system to its proper, intended functioning ("last known good").
+2. Once restored, the team validates that the system functions the way it was intended/had functioned in the past. This may require the involvement of the business unit that owns the affected system(s).
+3. If the operation of the system(s) had been interrupted (i.e., the system(s) had been taken offline or dropped from the network while triaged), restart the restored and validated system(s) and monitor for behavior.
+4. If the system had not been changed in any way but was taken offline (i.e., operations had been interrupted), restart the system and monitor for proper behavior.
+5. Update the documentation with the detail that was determined during this phase.
+6. Apprise Senior Management of progress.
+7. Continue to notify affected Customers and Partners with relevant updates as needed.
+8. Move to Phase V, Follow-up.
#### V - Post-Incident Analysis (Technical and Non-Technical)
@@ -670,27 +564,16 @@ been improved. It is recommended all security incidents be reviewed
shortly after resolution to determine where response could be improved.
Timeframes may extend to one to two weeks post-incident.
-1. Responders to the security incident (SIRT Team and technical security
- resource) meet to review the documentation collected during the security
- incident.
+1. Responders to the security incident (SIRT Team and technical security resource) meet to review the documentation collected during the security incident.
2. A "lessons learned" section is written and attached to the Incident ticket.
-
- 1. Evaluate the cost and impact of the security incident on Fleet using
- the documents provided by the SIRT and the technical security resource.
- 2. Determine what could be improved. This may include:
-
- * Systems and processes adjustments
- * Awareness training and documentation
- * Implementation of additional controls
-
- 3. Communicate these findings to Senior Management for approval and
- implementation of any recommendations made post-review of the security
- incident.
- 4. Carry out recommendations approved by Senior Management; sufficient
- budget, time, and resources should be committed to this activity.
-
-3. Ensure all incident-related information is recorded and retained as described
- in Fleet Auditing requirements and Data Retention standards.
+ - Evaluate the cost and impact of the security incident on Fleet using the documents provided by the SIRT and the technical security resource.
+ - Determine what could be improved. This may include:
+ - Systems and processes adjustments
+ - Awareness training and documentation
+ - Implementation of additional controls
+ - Communicate these findings to Senior Management for approval and implementation of any recommendations made post-review of the security incident.
+ - Carry out recommendations approved by Senior Management; sufficient budget, time, and resources should be committed to this activity.
+3. Ensure all incident-related information is recorded and retained as described in Fleet Auditing requirements and Data Retention standards.
4. Close the security incident.
#### Periodic Evaluation
@@ -717,11 +600,11 @@ Fleet Device Management is committed to conducting business in compliance with a
| Board of directors | Oversight over risk and internal control for information security, privacy, and compliance
Consults with executive leadership to understand Fleet's security mission and risks and provides guidance to bring them into alignment |
| Executive leadership | Approves capital expenditures for information security
Oversight over the execution of the information security risk management program
Communication path to Fleet's board of directors. Meets with the board regularly, including at least one official meeting a year
Aligns information security policy and posture based on Fleet's mission, strategic objectives, and risk appetite |
CTO | Oversight over information security in the software development process
Responsible for the design, development, implementation, operation, maintenance and monitoring of development and commercial cloud hosting security controls
Responsible for oversight over policy development
Responsible for implementing risk management in the development process |
-| Head of security | Oversight over the implementation of information security controls for infrastructure and IT processes
Responsible for the design, development, implementation, operation, maintenance, and monitoring of IT security controls
Communicate information security risks to executive leadership
Report information security risks annually to Fleet's leadership and gains approvals to bring risks to acceptable levels
Coordinate the development and maintenance of information security policies and standards
Work with applicable executive leadership to establish an information security framework and awareness program
Serve as liaison to the board of directors, law enforcement and legal department.
Oversight over identity management and access control processes |
+| Head of Security | Oversight over the implementation of information security controls for infrastructure and IT processes
Responsible for the design, development, implementation, operation, maintenance, and monitoring of IT security controls
Communicate information security risks to executive leadership
Report information security risks annually to Fleet's leadership and gains approvals to bring risks to acceptable levels
Coordinate the development and maintenance of information security policies and standards
Work with applicable executive leadership to establish an information security framework and awareness program
Serve as liaison to the board of directors, law enforcement and legal department.
Oversight over identity management and access control processes |
| System owners | Manage the confidentiality, integrity, and availability of the information systems for which they are responsible in compliance with Fleet policies on information security and privacy.
Approve of technical access and change requests for non-standard access |
| Employees, contractors, temporary workers, etc. | Acting at all times in a manner that does not place at risk the security of themselves, colleagues, and the information and resources they have use of
Helping to identify areas where risk management practices should be adopted
Adhering to company policies and standards of conduct Reporting incidents and observed anomalies or weaknesses |
-| Head of people operations | Ensuring employees and contractors are qualified and competent for their roles
Ensuring appropriate testing and background checks are completed
Ensuring that employees and relevant contractors are presented with company policies
Ensuring that employee performance and adherence to values is evaluated
Ensuring that employees receive appropriate security training |
-| Head of business operations | Responsible for oversight over third-party risk management process; responsible for review of vendor service contracts |
+| Head of People Operations | Ensuring employees and contractors are qualified and competent for their roles
Ensuring appropriate testing and background checks are completed
Ensuring that employees and relevant contractors are presented with company policies
Ensuring that employee performance and adherence to values is evaluated
Ensuring that employees receive appropriate security training |
+| Head of Business Operations | Responsible for oversight over third-party risk management process; responsible for review of vendor service contracts |
## Operations security and change management policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/)_
@@ -732,17 +615,13 @@ CTO | Oversight over information sec
Fleet policy requires
-1. all production changes, including but not limited to software deployment, feature toggle enablement, network infrastructure changes, and access control authorization updates, must be invoked through the approved change management process.
-
-2.each production change must maintain complete traceability to fully document the request, including the requestor, date/time of change, actions taken, and results.
-
-3. each production change must include proper approval.
-
- * The approvers are determined based on the type of change.
- * Approvers must be someone other than the author/executor of the change unless they are the DRI for that system.
- * Approvals may be automatically granted if specific criteria are met.
- The auto-approval criteria must be pre-approved by the Head of Security and
- fully documented and validated for each request.
+- All production changes, including but not limited to software deployment, feature toggle enablement, network infrastructure changes, and access control authorization updates, must be invoked through the approved change management process.
+- Each production change must maintain complete traceability to fully document the request, including the requestor, date/time of change, actions taken, and results.
+- Each production change must include proper approval.
+ - The approvers are determined based on the type of change.
+ - Approvers must be someone other than the author/executor of the change unless they are the DRI for that system.
+ - Approvals may be automatically granted if specific criteria are met.
+ - The auto-approval criteria must be pre-approved by the Head of Security and fully documented and validated for each request.
## Risk management policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/)_
@@ -753,13 +632,10 @@ Fleet policy requires
Fleet policy requires:
-1. A thorough risk assessment must be conducted to evaluate potential threats and vulnerabilities to the confidentiality, integrity, and availability of sensitive, confidential, and proprietary electronic information Fleet stores, transmits, and/or processes.
-
-2. Risk assessments must be performed with any major change to Fleet's business or technical operations and/or supporting infrastructure no less than once per year.
-
-3. Strategies shall be developed to mitigate or accept the risks identified in the risk assessment process.
-
-4. The risk register is monitored quarterly to assess compliance with the above policy, and document newly discovered or created risks.
+- A thorough risk assessment must be conducted to evaluate potential threats and vulnerabilities to the confidentiality, integrity, and availability of sensitive, confidential, and proprietary electronic information Fleet stores, transmits, and/or processes.
+- Risk assessments must be performed with any major change to Fleet's business or technical operations and/or supporting infrastructure no less than once per year.
+- Strategies shall be developed to mitigate or accept the risks identified in the risk assessment process.
+- The risk register is monitored quarterly to assess compliance with the above policy, and document newly discovered or created risks.
### Acceptable Risk Levels
@@ -782,28 +658,16 @@ All other risks must be individually reviewed and managed.
Fleet policy requires that:
1. Fleet software engineering and product development are required to follow security best practices. The product should be "Secure by Design" and "Secure by Default."
-
2. Fleet performs quality assurance activities. This may include:
-
- * Peer code reviews prior to merging new code into the main development branch
- (e.g., main branch)
- * Thorough product testing before releasing it to production (e.g., unit testing
- and integration testing)
-
+ - Peer code reviews prior to merging new code into the main development branch (e.g., main branch)
+ - Thorough product testing before releasing it to production (e.g., unit testing and integration testing)
3. Risk assessment activities (i.e., threat modeling) must be performed for a new product or extensive changes to an existing product.
-
4. Security requirements must be defined, tracked, and implemented.
-
5. Security analysis must be performed for any open source software and/or third-party components and dependencies included in Fleet software products.
-
6. Static application security testing (SAST) must be performed throughout development and before each release.
-
7. Dynamic application security testing (DAST) must be performed before each release.
-
8. All critical or high severity security findings must be remediated before each release.
-
9. All critical or high severity vulnerabilities discovered post-release must be remediated in the next release or as per the Fleet vulnerability management policy SLAs, whichever is sooner.
-
10. Any exception to the remediation of a finding must be documented and approved by the security team or CTO.
## Security policy management policy
@@ -814,29 +678,17 @@ Fleet policy requires that:
| @Jostableford | 2024-03-14 |
Fleet policy requires that:
-
-1. Fleet policies must be developed and maintained to meet all applicable compliance requirements and adhere to security best practices, including but not limited to:
-
-- SOC 2
-
-2. Fleet must annually review all policies.
-
-3. Fleet maintains all policy changes must be approved by Fleet's CTO or CEO. Additionally,
-
- * Major changes may require approval by Fleet CEO or designee;
- * Changes to policies and procedures related to product development may
- require approval by the CTO.
-
-3. Fleet maintains all policy documents with version control.
-
-4. Policy exceptions are handled on a case-by-case basis.
-
- * All exceptions must be fully documented with business purpose and reasons
- why the policy requirement cannot be met.
- * All policy exceptions must be approved by Fleet Head of Security and CEO.
- * An exception must have an expiration date no longer than one year from date
- of exception approval and it must be reviewed and re-evaluated on or before
- the expiration date.
+- Fleet policies must be developed and maintained to meet all applicable compliance requirements and adhere to security best practices, including but not limited to:
+ - SOC 2
+- Fleet must annually review all policies.
+ - Fleet maintains all policy changes must be approved by Fleet's CTO or CEO. Additionally:
+ - Major changes may require approval by Fleet CEO or designee;
+ - Changes to policies and procedures related to product development may require approval by the CTO.
+- Fleet maintains all policy documents with version control.
+- Policy exceptions are handled on a case-by-case basis.
+ - All exceptions must be fully documented with business purpose and reasons why the policy requirement cannot be met.
+ - All policy exceptions must be approved by Fleet Head of Security and CEO.
+ - An exception must have an expiration date no longer than one year from date of exception approval and it must be reviewed and re-evaluated on or before the expiration date.
## Third-party management policy
> _Created from [JupiterOne/security-policy-templates](https://github.com/JupiterOne/security-policy-templates). [CC BY-SA 4 license](https://creativecommons.org/licenses/by-sa/4.0/)_
@@ -845,23 +697,16 @@ Fleet policy requires that:
| -------------- | -------------- |
| @mikermcneil | 2022-06-01 |
-Fleet makes every effort to assure all third-party organizations are
-compliant and do not compromise the integrity, security, and privacy of Fleet
-or Fleet Customer data. Third Parties include Vendors, Customers, Partners,
-Subcontractors, and Contracted Developers.
+Fleet makes every effort to assure all third-party organizations are compliant and do not compromise the integrity, security, and privacy of Fleet or Fleet Customer data. Third Parties include Vendors, Customers, Partners, Subcontractors, and Contracted Developers.
-1. A list of approved vendors/partners must be maintained and reviewed annually.
-
-2. Approval from management, procurement, and security must be in place before onboarding any new vendor or contractor that impacts Fleet production systems. Additionally, all changes to existing contract agreements must be reviewed and approved before implementation.
-
-3. For any technology solution that needs to be integrated with Fleet production environment or operations, the security team must perform a Vendor Technology Review to understand and approve the risk. Periodic compliance assessment and SLA review may be required.
-
-4. Fleet Customers or Partners should not be allowed access outside of their own environment, meaning they cannot access, modify, or delete any data belonging to other third parties.
-
-5. Additional vendor agreements are obtained as required by applicable regulatory compliance requirements.
+- A list of approved vendors/partners must be maintained and reviewed annually.
+- Approval from management, procurement, and security must be in place before onboarding any new vendor or contractor that impacts Fleet production systems. Additionally, all changes to existing contract agreements must be reviewed and approved before implementation.
+- For any technology solution that needs to be integrated with Fleet production environment or operations, the security team must perform a Vendor Technology Review to understand and approve the risk. Periodic compliance assessment and SLA review may be required.
+- Fleet Customers or Partners should not be allowed access outside of their own environment, meaning they cannot access, modify, or delete any data belonging to other third parties.
+- Additional vendor agreements are obtained as required by applicable regulatory compliance requirements.
## Anti-corruption policy
> Fleet is committed to ethical business practices and compliance with the law. All Fleeties are required to comply with the "Foreign Corrup Practices Act" and anti-bribery laws and regulations in applicable jurisdictions including, but not limited to, the "UK Bribery Act 2010", "European Commission on Anti-Corruption" and others. The policies set forth in [this document](https://docs.google.com/document/d/16iHhLhAV0GS2mBrDKIBaIRe_pmXJrA1y7-gTWNxSR6c/edit?usp=sharing) go over Fleet's anti-corruption policy in detail.
-
+
From 66dd003f7d6ca52ae917407451de76fa942dc0e0 Mon Sep 17 00:00:00 2001
From: Rachael Shaw
Date: Thu, 28 Mar 2024 13:23:48 -0500
Subject: [PATCH 21/64] Add TCC tables with all available data (#17935)
Add more complete versions of the TCC tables to canary team (research
for #16899)
Also added queries to run on the canary team.
---
...t-software-permissions-system.queries.yaml | 5 +++
...ect-software-permissions-user.queries.yaml | 5 +++
it-and-security/teams/workstations-canary.yml | 32 +++++++++++++++++--
3 files changed, 40 insertions(+), 2 deletions(-)
create mode 100644 it-and-security/lib/collect-software-permissions-system.queries.yaml
create mode 100644 it-and-security/lib/collect-software-permissions-user.queries.yaml
diff --git a/it-and-security/lib/collect-software-permissions-system.queries.yaml b/it-and-security/lib/collect-software-permissions-system.queries.yaml
new file mode 100644
index 0000000000..0f576ffcf7
--- /dev/null
+++ b/it-and-security/lib/collect-software-permissions-system.queries.yaml
@@ -0,0 +1,5 @@
+- name: Collect software permissions (system)
+ description: "Research for #16899"
+ query: SELECT * from tcc_system;
+ interval: 3600 # 1 hour
+ platform: darwin
\ No newline at end of file
diff --git a/it-and-security/lib/collect-software-permissions-user.queries.yaml b/it-and-security/lib/collect-software-permissions-user.queries.yaml
new file mode 100644
index 0000000000..b8b0e7c75b
--- /dev/null
+++ b/it-and-security/lib/collect-software-permissions-user.queries.yaml
@@ -0,0 +1,5 @@
+- name: Collect software permissions (user)
+ description: "Research for #16899"
+ query: SELECT * from tcc_user;
+ interval: 3600 # 1 hour
+ platform: darwin
\ No newline at end of file
diff --git a/it-and-security/teams/workstations-canary.yml b/it-and-security/teams/workstations-canary.yml
index e5ad3636eb..e2550b4b88 100644
--- a/it-and-security/teams/workstations-canary.yml
+++ b/it-and-security/teams/workstations-canary.yml
@@ -26,14 +26,40 @@ agent_options:
platforms:
darwin:
auto_table_construction:
- tcc:
+ tcc_system:
path: /Library/Application Support/com.apple.TCC/TCC.db
- query: 'select service, client, auth_value, auth_reason from access'
+ query: 'select service, client, client_type, auth_value, auth_reason, auth_version, csreq, policy_id, indirect_object_identifier, indirect_object_identifier_type, indirect_object_code_identity, flags, last_modified from access'
columns:
- service
- client
+ - client_type
- auth_value
- auth_reason
+ - auth_version
+ - csreq
+ - policy_id
+ - indirect_object_identifier
+ - indirect_object_identifier_type
+ - indirect_object_code_identity
+ - flags
+ - last_modified
+ tcc_user:
+ path: /Users/%/Library/Application Support/com.apple.TCC/TCC.db
+ query: 'select service, client, client_type, auth_value, auth_reason, auth_version, csreq, policy_id, indirect_object_identifier, indirect_object_identifier_type, indirect_object_code_identity, flags, last_modified from access'
+ columns:
+ - service
+ - client
+ - client_type
+ - auth_value
+ - auth_reason
+ - auth_version
+ - csreq
+ - policy_id
+ - indirect_object_identifier
+ - indirect_object_identifier_type
+ - indirect_object_code_identity
+ - flags
+ - last_modified
controls:
enable_disk_encryption: true
macos_settings:
@@ -92,3 +118,5 @@ queries:
- path: ../lib/collect-failed-login-attempts.queries.yml
- path: ../lib/collect-usb-devices.queries.yml
- path: ../lib/collect-vs-code-extensions.queries.yml
+ - path: ../lib/collect-software-permissions-system.queries.yml
+ - path: ../lib/collect-software-permissions-user.queries.yml
From 48ee01950766043cbd261c566a49e7cf259c543d Mon Sep 17 00:00:00 2001
From: Roberto Dip
Date: Thu, 28 Mar 2024 11:35:35 -0300
Subject: [PATCH 22/64] fix unreleased issues for macOS DDM
for #17924 and #17923
---
server/datastore/mysql/apple_mdm.go | 18 ++-
server/datastore/mysql/apple_mdm_test.go | 111 ++++++++++++++
server/fleet/datastore.go | 7 +-
server/mock/datastore_mock.go | 12 +-
server/service/apple_mdm.go | 20 ++-
server/service/integration_ddm_test.go | 183 +++++++++++++++--------
server/service/integration_mdm_test.go | 22 ++-
7 files changed, 279 insertions(+), 94 deletions(-)
diff --git a/server/datastore/mysql/apple_mdm.go b/server/datastore/mysql/apple_mdm.go
index b22f178300..1dac196ae2 100644
--- a/server/datastore/mysql/apple_mdm.go
+++ b/server/datastore/mysql/apple_mdm.go
@@ -269,6 +269,7 @@ func (ds *Datastore) DeleteMDMAppleConfigProfileByDeprecatedID(ctx context.Conte
}
func (ds *Datastore) DeleteMDMAppleConfigProfile(ctx context.Context, profileUUID string) error {
+ // TODO(roberto): this seems confusing to me, we should have a separate datastore method.
if strings.HasPrefix(profileUUID, fleet.MDMAppleDeclarationUUIDPrefix) {
return ds.deleteMDMAppleDeclaration(ctx, profileUUID)
}
@@ -3688,10 +3689,10 @@ func batchSetDeclarationLabelAssociationsDB(ctx context.Context, tx sqlx.ExtCont
func (ds *Datastore) MDMAppleDDMDeclarationsToken(ctx context.Context, hostUUID string) (*fleet.MDMAppleDDMDeclarationsToken, error) {
const stmt = `
SELECT
- md5((count(0) + group_concat(hex(mad.checksum)
+ COALESCE(MD5((count(0) + GROUP_CONCAT(HEX(mad.checksum)
ORDER BY
- mad.uploaded_at DESC separator ''))) AS checksum,
- max(mad.created_at) AS latest_created_timestamp
+ mad.uploaded_at DESC separator ''))), '') AS checksum,
+ COALESCE(MAX(mad.created_at), NOW()) AS latest_created_timestamp
FROM
host_mdm_apple_declarations hmad
JOIN mdm_apple_declarations mad ON hmad.declaration_uuid = mad.declaration_uuid
@@ -3947,10 +3948,12 @@ ON DUPLICATE KEY UPDATE
return ctxerr.Wrap(ctx, err, "updating host declarations")
}
-func (ds *Datastore) MDMAppleSetDeclarationsAsVerifying(ctx context.Context, hostUUID string) error {
+func (ds *Datastore) MDMAppleSetPendingDeclarationsAs(ctx context.Context, hostUUID string, status *fleet.MDMDeliveryStatus, detail string) error {
stmt := `
UPDATE host_mdm_apple_declarations
- SET status = ?
+ SET
+ status = ?,
+ detail = ?
WHERE
operation_type = ?
AND status = ?
@@ -3958,7 +3961,10 @@ func (ds *Datastore) MDMAppleSetDeclarationsAsVerifying(ctx context.Context, hos
`
_, err := ds.writer(ctx).ExecContext(
- ctx, stmt, fleet.MDMDeliveryVerifying,
+ ctx, stmt,
+ // SET ...
+ status, detail,
+ // WHERE ...
fleet.MDMOperationTypeInstall, fleet.MDMDeliveryPending, hostUUID,
)
return ctxerr.Wrap(ctx, err, "updating host declaration status to verifying")
diff --git a/server/datastore/mysql/apple_mdm_test.go b/server/datastore/mysql/apple_mdm_test.go
index d989cc2719..6829d32dec 100644
--- a/server/datastore/mysql/apple_mdm_test.go
+++ b/server/datastore/mysql/apple_mdm_test.go
@@ -69,6 +69,8 @@ func TestMDMApple(t *testing.T) {
{"TestMDMAppleDeleteHostDEPAssignments", testMDMAppleDeleteHostDEPAssignments},
{"LockUnlockWipeMacOS", testLockUnlockWipeMacOS},
{"ScreenDEPAssignProfileSerialsForCooldown", testScreenDEPAssignProfileSerialsForCooldown},
+ {"MDMAppleDDMDeclarationsToken", testMDMAppleDDMDeclarationsToken},
+ {"MDMAppleSetPendingDeclarationsAs", testMDMAppleSetPendingDeclarationsAs},
}
for _, c := range cases {
@@ -4674,6 +4676,115 @@ func testScreenDEPAssignProfileSerialsForCooldown(t *testing.T, ds *Datastore) {
require.Empty(t, assign)
}
+func testMDMAppleDDMDeclarationsToken(t *testing.T, ds *Datastore) {
+ ctx := context.Background()
+ toks, err := ds.MDMAppleDDMDeclarationsToken(ctx, "not-exists")
+ require.NoError(t, err)
+ require.Empty(t, toks.DeclarationsToken)
+
+ decl, err := ds.NewMDMAppleDeclaration(ctx, &fleet.MDMAppleDeclaration{
+ Identifier: "decl-1",
+ Name: "decl-1",
+ })
+ require.NoError(t, err)
+ err = ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl.DeclarationUUID}, nil)
+ require.NoError(t, err)
+
+ toks, err = ds.MDMAppleDDMDeclarationsToken(ctx, "not-exists")
+ require.NoError(t, err)
+ require.Empty(t, toks.DeclarationsToken)
+ require.NotZero(t, toks.Timestamp)
+
+ host1, err := ds.NewHost(ctx, &fleet.Host{
+ Hostname: "test-host1-name",
+ OsqueryHostID: ptr.String("1337"),
+ NodeKey: ptr.String("1337"),
+ UUID: "test-uuid-1",
+ TeamID: nil,
+ Platform: "darwin",
+ })
+ require.NoError(t, err)
+ nanoEnroll(t, ds, host1, true)
+ err = ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl.DeclarationUUID}, nil)
+ require.NoError(t, err)
+
+ toks, err = ds.MDMAppleDDMDeclarationsToken(ctx, host1.UUID)
+ require.NoError(t, err)
+ require.NotEmpty(t, toks.DeclarationsToken)
+ require.NotZero(t, toks.Timestamp)
+ oldTok := toks.DeclarationsToken
+
+ decl2, err := ds.NewMDMAppleDeclaration(ctx, &fleet.MDMAppleDeclaration{
+ Identifier: "decl-2",
+ Name: "decl-2",
+ })
+ require.NoError(t, err)
+ err = ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl2.DeclarationUUID}, nil)
+ require.NoError(t, err)
+
+ toks, err = ds.MDMAppleDDMDeclarationsToken(ctx, host1.UUID)
+ require.NoError(t, err)
+ require.NotEmpty(t, toks.DeclarationsToken)
+ require.NotZero(t, toks.Timestamp)
+ require.NotEqual(t, oldTok, toks.DeclarationsToken)
+ oldTok = toks.DeclarationsToken
+
+ ds.DeleteMDMAppleConfigProfile(ctx, decl.DeclarationUUID)
+ err = ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl2.DeclarationUUID}, nil)
+ require.NoError(t, err)
+
+ toks, err = ds.MDMAppleDDMDeclarationsToken(ctx, host1.UUID)
+ require.NoError(t, err)
+ require.NotEmpty(t, toks.DeclarationsToken)
+ require.NotZero(t, toks.Timestamp)
+ require.NotEqual(t, oldTok, toks.DeclarationsToken)
+}
+
+func testMDMAppleSetPendingDeclarationsAs(t *testing.T, ds *Datastore) {
+ ctx := context.Background()
+
+ for i := 0; i < 10; i++ {
+ _, err := ds.NewMDMAppleDeclaration(ctx, &fleet.MDMAppleDeclaration{
+ Identifier: fmt.Sprintf("decl-%d", i),
+ Name: fmt.Sprintf("decl-%d", i),
+ })
+ require.NoError(t, err)
+ }
+
+ checkStatus := func(declarations []fleet.HostMDMAppleProfile, wantStatus fleet.MDMDeliveryStatus, wantDetail string) {
+ for _, d := range declarations {
+ require.Equal(t, &wantStatus, d.Status)
+ require.Equal(t, wantDetail, d.Detail)
+ }
+ }
+
+ h, err := ds.NewHost(ctx, &fleet.Host{
+ Hostname: "test-host1-name",
+ OsqueryHostID: ptr.String("1337"),
+ NodeKey: ptr.String("1337"),
+ UUID: "test-uuid-1",
+ TeamID: nil,
+ Platform: "darwin",
+ })
+ require.NoError(t, err)
+ nanoEnroll(t, ds, h, true)
+
+ uuids, err := ds.MDMAppleBatchSetHostDeclarationState(ctx)
+ require.NoError(t, err)
+ require.Equal(t, h.UUID, uuids[0])
+
+ profs, err := ds.GetHostMDMAppleProfiles(ctx, h.UUID)
+ require.NoError(t, err)
+ require.Len(t, profs, 10)
+ checkStatus(profs, fleet.MDMDeliveryPending, "")
+
+ err = ds.MDMAppleSetPendingDeclarationsAs(ctx, h.UUID, &fleet.MDMDeliveryFailed, "mock error")
+ require.NoError(t, err)
+ profs, err = ds.GetHostMDMAppleProfiles(ctx, h.UUID)
+ require.NoError(t, err)
+ checkStatus(profs, fleet.MDMDeliveryFailed, "mock error")
+}
+
func TestMDMAppleProfileVerification(t *testing.T) {
ds := CreateMySQLDS(t)
ctx := context.Background()
diff --git a/server/fleet/datastore.go b/server/fleet/datastore.go
index 99ba5b7f0a..816f706f6a 100644
--- a/server/fleet/datastore.go
+++ b/server/fleet/datastore.go
@@ -1191,9 +1191,10 @@ type Datastore interface {
// It also takes care of cleaning up all host declarations that are
// pending removal.
MDMAppleStoreDDMStatusReport(ctx context.Context, hostUUID string, updates []*MDMAppleHostDeclaration) error
- // MDMAppleSetDeclarationsAsVerifying updates all
- // ("pending", "install") declarations for a host to be ("verifying", "install")
- MDMAppleSetDeclarationsAsVerifying(ctx context.Context, hostUUID string) error
+ // MDMAppleSetPendingDeclarationsAs updates all ("pending", "install")
+ // declarations for a host to be ("verifying", status), where status is
+ // the provided value.
+ MDMAppleSetPendingDeclarationsAs(ctx context.Context, hostUUID string, status *MDMDeliveryStatus, detail string) error
///////////////////////////////////////////////////////////////////////////////
// Microsoft MDM
diff --git a/server/mock/datastore_mock.go b/server/mock/datastore_mock.go
index 66290f4095..26510aaac0 100644
--- a/server/mock/datastore_mock.go
+++ b/server/mock/datastore_mock.go
@@ -792,7 +792,7 @@ type MDMAppleBatchSetHostDeclarationStateFunc func(ctx context.Context) ([]strin
type MDMAppleStoreDDMStatusReportFunc func(ctx context.Context, hostUUID string, updates []*fleet.MDMAppleHostDeclaration) error
-type MDMAppleSetDeclarationsAsVerifyingFunc func(ctx context.Context, hostUUID string) error
+type MDMAppleSetPendingDeclarationsAsFunc func(ctx context.Context, hostUUID string, status *fleet.MDMDeliveryStatus, detail string) error
type WSTEPStoreCertificateFunc func(ctx context.Context, name string, crt *x509.Certificate) error
@@ -2060,8 +2060,8 @@ type DataStore struct {
MDMAppleStoreDDMStatusReportFunc MDMAppleStoreDDMStatusReportFunc
MDMAppleStoreDDMStatusReportFuncInvoked bool
- MDMAppleSetDeclarationsAsVerifyingFunc MDMAppleSetDeclarationsAsVerifyingFunc
- MDMAppleSetDeclarationsAsVerifyingFuncInvoked bool
+ MDMAppleSetPendingDeclarationsAsFunc MDMAppleSetPendingDeclarationsAsFunc
+ MDMAppleSetPendingDeclarationsAsFuncInvoked bool
WSTEPStoreCertificateFunc WSTEPStoreCertificateFunc
WSTEPStoreCertificateFuncInvoked bool
@@ -4931,11 +4931,11 @@ func (s *DataStore) MDMAppleStoreDDMStatusReport(ctx context.Context, hostUUID s
return s.MDMAppleStoreDDMStatusReportFunc(ctx, hostUUID, updates)
}
-func (s *DataStore) MDMAppleSetDeclarationsAsVerifying(ctx context.Context, hostUUID string) error {
+func (s *DataStore) MDMAppleSetPendingDeclarationsAs(ctx context.Context, hostUUID string, status *fleet.MDMDeliveryStatus, detail string) error {
s.mu.Lock()
- s.MDMAppleSetDeclarationsAsVerifyingFuncInvoked = true
+ s.MDMAppleSetPendingDeclarationsAsFuncInvoked = true
s.mu.Unlock()
- return s.MDMAppleSetDeclarationsAsVerifyingFunc(ctx, hostUUID)
+ return s.MDMAppleSetPendingDeclarationsAsFunc(ctx, hostUUID, status, detail)
}
func (s *DataStore) WSTEPStoreCertificate(ctx context.Context, name string, crt *x509.Certificate) error {
diff --git a/server/service/apple_mdm.go b/server/service/apple_mdm.go
index 1f19ede881..81e80a2653 100644
--- a/server/service/apple_mdm.go
+++ b/server/service/apple_mdm.go
@@ -442,15 +442,18 @@ func (svc *Service) NewMDMAppleDeclaration(ctx context.Context, teamID uint, r i
d := fleet.NewMDMAppleDeclaration(data, tmID, name, rawDecl.Type, rawDecl.Identifier)
- // TODO(roberto): Is this already handled in NewMDMAppleDeclaration? Could we add the labels as well?
+ // TODO(roberto): this should be part of fleet.NewMDMAppleDeclaration
d.Labels = validatedLabels
- d.TeamID = tmID
decl, err := svc.ds.NewMDMAppleDeclaration(ctx, d)
if err != nil {
return nil, err
}
+ if err := svc.ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl.DeclarationUUID}, nil); err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "bulk set pending host declarations")
+ }
+
var (
actTeamID *uint
actTeamName *string
@@ -2603,6 +2606,8 @@ func (svc *MDMAppleCheckinAndCommandService) CommandAndReportResults(r *mdm.Requ
if err := svc.ds.CleanMacOSMDMLock(r.Context, cmdResult.UDID); err != nil {
return nil, ctxerr.Wrap(r.Context, err, "cleaning macOS host lock/wipe status")
}
+
+ return nil, nil
}
// We explicitly get the request type because it comes empty. There's a
@@ -2639,8 +2644,11 @@ func (svc *MDMAppleCheckinAndCommandService) CommandAndReportResults(r *mdm.Requ
return nil, svc.ds.UpdateHostLockWipeStatusFromAppleMDMResult(r.Context, cmdResult.UDID, cmdResult.CommandUUID, requestType, cmdResult.Status == fleet.MDMAppleStatusAcknowledged)
}
case "DeclarativeManagement":
- // set "pending-install" profiles to "verifying"
- err := svc.ds.MDMAppleSetDeclarationsAsVerifying(r.Context, cmdResult.UDID)
+ // set "pending-install" profiles to "verifying" or "failed"
+ // depending on the status of the DeviceManagement command
+ status := mdmAppleDeliveryStatusFromCommandStatus(cmdResult.Status)
+ detail := fmt.Sprintf("%s. Make sure the host is on macOS 13 or higher.", apple_mdm.FmtErrorChain(cmdResult.ErrorChain))
+ err := svc.ds.MDMAppleSetPendingDeclarationsAs(r.Context, cmdResult.UDID, status, detail)
return nil, ctxerr.Wrap(r.Context, err, "update declaration status on DeclarativeManagement ack")
}
@@ -3414,10 +3422,6 @@ func (svc *MDMAppleDDMService) handleDeclarationStatus(ctx context.Context, dm *
}
}
- if len(updates) == 0 {
- return nil
- }
-
// MDMAppleStoreDDMStatusReport takes care of cleaning ("pending", "remove")
// pairs for the host.
//
diff --git a/server/service/integration_ddm_test.go b/server/service/integration_ddm_test.go
index e8c77a192d..4444649ae8 100644
--- a/server/service/integration_ddm_test.go
+++ b/server/service/integration_ddm_test.go
@@ -8,7 +8,6 @@ import (
"fmt"
"io"
"net/http"
- "os"
"strings"
"testing"
"time"
@@ -16,8 +15,8 @@ import (
"github.com/fleetdm/fleet/v4/pkg/mdm/mdmtest"
"github.com/fleetdm/fleet/v4/server/datastore/mysql"
"github.com/fleetdm/fleet/v4/server/fleet"
+ "github.com/fleetdm/fleet/v4/server/mdm/nanomdm/mdm"
"github.com/fleetdm/fleet/v4/server/ptr"
- kitlog "github.com/go-kit/log"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/require"
@@ -34,9 +33,6 @@ func (s *integrationMDMTestSuite) TestAppleDDMBatchUpload() {
"DataAssetReference": "com.fleet.asset.bash" %s
}
}`
- // TODO: figure out the best way to do this. We might even consider
- // starting a different test suite.
- t.Cleanup(func() { s.cleanupDeclarations(t) })
newDeclBytes := func(i int, payload ...string) []byte {
var p string
@@ -201,8 +197,6 @@ func (s *integrationMDMTestSuite) TestMDMAppleDeviceManagementRequests() {
return strings.ToUpper(csum)
}
- t.Cleanup(func() { s.cleanupDeclarations(t) })
-
insertDeclaration := func(t *testing.T, decl fleet.MDMAppleDeclaration) {
stmt := `
INSERT INTO mdm_apple_declarations (
@@ -507,27 +501,27 @@ INSERT INTO host_mdm_apple_declarations (
func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
t := s.T()
ctx := context.Background()
- // TODO: use config logger or take into account FLEET_INTEGRATION_TESTS_DISABLE_LOG
- logger := kitlog.NewJSONLogger(os.Stdout)
- // TODO: use endpoints once those are available.
- addDeclaration := func(identifier string, teamID uint) {
- stmt := `
- INSERT INTO mdm_apple_declarations
- (declaration_uuid, team_id, identifier, name, raw_json, checksum)
- VALUES
- (UUID(), ?, ?, UUID(), ?, HEX(MD5(raw_json)) )`
- mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
- _, err := tx.ExecContext(ctx, stmt, teamID, identifier, declarationForTest(identifier))
- return err
- })
+ addDeclaration := func(identifier string, teamID uint) string {
+ fields := map[string][]string{}
+ if teamID > 0 {
+ fields["team_id"] = []string{fmt.Sprintf("%d", teamID)}
+ }
+ body, headers := generateNewProfileMultipartRequest(
+ t, identifier+".json", declarationForTest(identifier), s.token, fields,
+ )
+ res := s.DoRawWithHeaders("POST", "/api/latest/fleet/configuration_profiles", body.Bytes(), http.StatusOK, headers)
+ var resp newMDMConfigProfileResponse
+ err := json.NewDecoder(res.Body).Decode(&resp)
+ require.NoError(t, err)
+ require.NotEmpty(t, resp.ProfileUUID)
+ require.Equal(t, "d", string(resp.ProfileUUID[0]))
+ return resp.ProfileUUID
}
- deleteDeclaration := func(identifier string, teamID uint) {
- mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
- _, err := tx.ExecContext(ctx, "DELETE FROM mdm_apple_declarations WHERE team_id = ? AND identifier = ?", teamID, identifier)
- return err
- })
+ deleteDeclaration := func(declUUID string) {
+ var deleteResp deleteMDMConfigProfileResponse
+ s.DoJSON("DELETE", fmt.Sprintf("/api/latest/fleet/configuration_profiles/%s", declUUID), nil, http.StatusOK, &deleteResp)
}
// create a team
@@ -540,10 +534,6 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
require.NotZero(t, createTeamResp.Team.ID)
team = createTeamResp.Team
- // TODO: figure out the best way to do this. We might even consider
- // starting a different test suite.
- t.Cleanup(func() { s.cleanupDeclarations(t) })
-
checkNoCommands := func(d *mdmtest.TestAppleMDMClient) {
cmd, err := d.Idle()
require.NoError(t, err)
@@ -602,18 +592,18 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
mdmHost, device := createHostThenEnrollMDM(s.ds, s.server.URL, t)
// trigger the reconciler, no error
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// declarativeManagement command is not sent.
checkNoCommands(device)
// add global declarations
- addDeclaration("I1", 0)
+ d1UUID := addDeclaration("I1", 0)
addDeclaration("I2", 0)
// reconcile again, this time new declarations were added
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// TODO: check command is pending
@@ -622,15 +612,15 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkDDMSync(device)
// reconcile again, commands for the uploaded declarations are already sent
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// no new commands are sent
checkNoCommands(device)
// delete a declaration
- deleteDeclaration("I1", 0)
+ deleteDeclaration(d1UUID)
// reconcile again
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// a DDM sync is triggered
checkDDMSync(device)
@@ -638,7 +628,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
// add a new host
_, deviceTwo := createHostThenEnrollMDM(s.ds, s.server.URL, t)
// reconcile again
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// DDM sync is triggered only for the new host
checkNoCommands(device)
@@ -649,7 +639,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
addHostsToTeamRequest{TeamID: &team.ID, HostIDs: []uint{mdmHost.ID}}, http.StatusOK)
// reconcile
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// DDM sync is triggered only for the transferred host
@@ -658,7 +648,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkNoCommands(deviceTwo)
// reconcile
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// nobody receives commands this time
checkNoCommands(device)
@@ -669,7 +659,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
addDeclaration("I2", team.ID)
// reconcile
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// DDM sync is triggered for the host in the team
checkDDMSync(device)
@@ -681,7 +671,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
addHostsToTeamRequest{TeamID: &team.ID, HostIDs: []uint{mdmHostThree.ID}}, http.StatusOK)
// reconcile
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// DDM sync is triggered only for the new host
checkNoCommands(device)
@@ -689,7 +679,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkDDMSync(deviceThree)
// no new commands after another reconciliation
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
checkNoCommands(device)
checkNoCommands(deviceTwo)
@@ -731,7 +721,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
)
// reconcile
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// DDM sync is triggered only for the host with the label
checkNoCommands(device)
@@ -742,12 +732,6 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
t := s.T()
ctx := context.Background()
- // TODO: use config logger or take into account FLEET_INTEGRATION_TESTS_DISABLE_LOG
- logger := kitlog.NewJSONLogger(os.Stdout)
-
- // TODO: figure out the best way to do this. We might even consider
- // starting a different test suite.
- t.Cleanup(func() { s.cleanupDeclarations(t) })
assertHostDeclarations := func(hostUUID string, wantDecls []*fleet.MDMAppleHostDeclaration) {
var gotDecls []*fleet.MDMAppleHostDeclaration
@@ -768,7 +752,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: declarations}, http.StatusNoContent)
// reconcile profiles
- err := ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err := ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
// declarations are ("install", "pending") after the cron run
@@ -851,7 +835,7 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: declarations}, http.StatusNoContent)
// reconcile profiles
- err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, logger)
+ err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
require.NoError(t, err)
assertHostDeclarations(mdmHost.UUID, []*fleet.MDMAppleHostDeclaration{
{Identifier: "I1", Status: &fleet.MDMDeliveryVerified, OperationType: fleet.MDMOperationTypeInstall},
@@ -881,6 +865,89 @@ func (s *integrationMDMTestSuite) TestAppleDDMStatusReport() {
})
}
+func (s *integrationMDMTestSuite) TestDDMUnsupportedDevice() {
+ t := s.T()
+ ctx := context.Background()
+ fleetHost, mdmDevice := createHostThenEnrollMDM(s.ds, s.server.URL, t)
+
+ getProfiles := func(h *fleet.Host) map[string]*fleet.HostMDMAppleProfile {
+ profs, err := s.ds.GetHostMDMAppleProfiles(ctx, h.UUID)
+ require.NoError(t, err)
+ out := make(map[string]*fleet.HostMDMAppleProfile, len(profs))
+ for _, p := range profs {
+ out[p.Identifier] = &p
+ }
+
+ return out
+ }
+
+ declarations := []fleet.MDMProfileBatchPayload{
+ {Name: "N1.json", Contents: declarationForTest("I1")},
+ {Name: "N2.json", Contents: declarationForTest("I2")},
+ }
+ // add global declarations
+ s.Do("POST", "/api/v1/fleet/mdm/profiles/batch", batchSetMDMProfilesRequest{Profiles: declarations}, http.StatusNoContent)
+
+ // reconcile declarations
+ err := ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
+ require.NoError(t, err)
+
+ // declaration is pending
+ profs := getProfiles(fleetHost)
+ require.Equal(t, &fleet.MDMDeliveryPending, profs["I1"].Status)
+ require.Equal(t, &fleet.MDMDeliveryPending, profs["I2"].Status)
+
+ cmd, err := mdmDevice.Idle()
+ require.NoError(t, err)
+ require.Equal(t, "DeclarativeManagement", cmd.Command.RequestType)
+
+ // simulate an error returned by devices that don't support DDM
+ errChain := []mdm.ErrorChain{
+ {
+ ErrorCode: 4,
+ ErrorDomain: "RMErrorDomain",
+ LocalizedDescription: "Feature Disabled: DeclarativeManagement is disabled.",
+ },
+ }
+ cmd, err = mdmDevice.Err(cmd.CommandUUID, errChain)
+ require.NoError(t, err)
+ require.Nil(t, cmd)
+
+ // profiles are failed
+ profs = getProfiles(fleetHost)
+ require.Equal(t, &fleet.MDMDeliveryFailed, profs["I1"].Status)
+ require.Contains(t, profs["I1"].Detail, "Feature Disabled")
+ require.Equal(t, &fleet.MDMDeliveryFailed, profs["I2"].Status)
+ require.Contains(t, profs["I2"].Detail, "Feature Disabled")
+
+}
+
+func (s *integrationMDMTestSuite) TestDDMNoDeclarationsLeft() {
+ t := s.T()
+ _, mdmDevice := createHostThenEnrollMDM(s.ds, s.server.URL, t)
+
+ res, err := mdmDevice.DeclarativeManagement("tokens")
+ require.NoError(t, err)
+ require.Equal(t, http.StatusOK, res.StatusCode)
+ var tok fleet.MDMAppleDDMTokensResponse
+ err = json.NewDecoder(res.Body).Decode(&tok)
+ require.NoError(t, err)
+ require.Empty(t, tok.SyncTokens.DeclarationsToken)
+ require.NotEmpty(t, tok.SyncTokens.Timestamp)
+
+ res, err = mdmDevice.DeclarativeManagement("declaration-items")
+ require.NoError(t, err)
+ require.Equal(t, http.StatusOK, res.StatusCode)
+ var items fleet.MDMAppleDDMDeclarationItemsResponse
+ err = json.NewDecoder(res.Body).Decode(&items)
+ require.NoError(t, err)
+ require.Empty(t, items.DeclarationsToken)
+ require.Empty(t, items.Declarations.Activations)
+ require.Empty(t, items.Declarations.Configurations)
+ require.Empty(t, items.Declarations.Assets)
+ require.Empty(t, items.Declarations.Management)
+}
+
func declarationForTest(identifier string) []byte {
return []byte(fmt.Sprintf(`
{
@@ -891,19 +958,3 @@ func declarationForTest(identifier string) []byte {
"Identifier": "%s"
}`, identifier))
}
-
-func (s *integrationMDMTestSuite) cleanupDeclarations(t *testing.T) {
- ctx := context.Background()
- // TODO: figure out the best way to do this. We might even consider
- // starting a different test suite.
- // delete declarations to not affect other tests
- mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
- _, err := tx.ExecContext(ctx, "DELETE FROM mdm_apple_declarations")
- return err
- })
- mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
- _, err := tx.ExecContext(ctx, "DELETE FROM host_mdm_apple_declarations")
- return err
- })
-
-}
diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go
index 78bc0076d7..4b6bbfc23f 100644
--- a/server/service/integration_mdm_test.go
+++ b/server/service/integration_mdm_test.go
@@ -87,6 +87,7 @@ type integrationMDMTestSuite struct {
mdmStorage *mysql.NanoMDMStorage
worker *worker.Worker
mdmCommander *apple_mdm.MDMAppleCommander
+ logger kitlog.Logger
}
func (s *integrationMDMTestSuite) SetupSuite() {
@@ -158,10 +159,15 @@ func (s *integrationMDMTestSuite) SetupSuite() {
if os.Getenv("FLEET_INTEGRATION_TESTS_DISABLE_LOG") != "" {
cronLog = kitlog.NewNopLogger()
}
+ serverLogger := kitlog.NewJSONLogger(os.Stdout)
+ if os.Getenv("FLEET_INTEGRATION_TESTS_DISABLE_LOG") != "" {
+ serverLogger = kitlog.NewNopLogger()
+ }
config := TestServerOpts{
License: &fleet.LicenseInfo{
Tier: fleet.TierPremium,
},
+ Logger: serverLogger,
FleetConfig: &fleetCfg,
MDMStorage: mdmStorage,
DEPStorage: depStorage,
@@ -241,9 +247,6 @@ func (s *integrationMDMTestSuite) SetupSuite() {
},
APNSTopic: "com.apple.mgmt.External.10ac3ce5-4668-4e58-b69a-b2b5ce667589",
}
- if os.Getenv("FLEET_INTEGRATION_TESTS_DISABLE_LOG") != "" {
- config.Logger = kitlog.NewNopLogger()
- }
users, server := RunServerForTestsWithDS(s.T(), s.ds, &config)
s.server = server
s.users = users
@@ -257,6 +260,7 @@ func (s *integrationMDMTestSuite) SetupSuite() {
s.profileSchedule = profileSchedule
s.mdmStorage = mdmStorage
s.mdmCommander = mdmCommander
+ s.logger = serverLogger
fleetdmSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
status := s.fleetDMNextCSRStatus.Swap(http.StatusOK)
@@ -341,6 +345,16 @@ func (s *integrationMDMTestSuite) TearDownTest() {
_, err := q.ExecContext(ctx, "DELETE FROM mdm_windows_enrollments")
return err
})
+
+ // clear any lingering declarations
+ mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
+ _, err := tx.ExecContext(ctx, "DELETE FROM mdm_apple_declarations")
+ return err
+ })
+ mysql.ExecAdhocSQL(t, s.ds, func(tx sqlx.ExtContext) error {
+ _, err := tx.ExecContext(ctx, "DELETE FROM host_mdm_apple_declarations")
+ return err
+ })
}
func (s *integrationMDMTestSuite) mockDEPResponse(handler http.Handler) {
@@ -8706,8 +8720,6 @@ func (s *integrationMDMTestSuite) TestMDMConfigProfileCRUD() {
testTeam, err := s.ds.NewTeam(ctx, &fleet.Team{Name: "TestTeam"})
require.NoError(t, err)
- t.Cleanup(func() { s.cleanupDeclarations(t) })
-
assertAppleProfile := func(filename, name, ident string, teamID uint, labelNames []string, wantStatus int, wantErrMsg string) string {
fields := map[string][]string{
"labels": labelNames,
From 57793c27a0218879a088bae4f6818a603a237a76 Mon Sep 17 00:00:00 2001
From: Robert Fairburn <8029478+rfairburn@users.noreply.github.com>
Date: Thu, 28 Mar 2024 13:55:41 -0500
Subject: [PATCH 23/64] Remove WAF from dogfood (#17940)
---
infrastructure/dogfood/terraform/aws-tf-module/free.tf | 6 ------
infrastructure/dogfood/terraform/aws-tf-module/main.tf | 6 ------
2 files changed, 12 deletions(-)
diff --git a/infrastructure/dogfood/terraform/aws-tf-module/free.tf b/infrastructure/dogfood/terraform/aws-tf-module/free.tf
index 8a6336d0be..4efc3999b9 100644
--- a/infrastructure/dogfood/terraform/aws-tf-module/free.tf
+++ b/infrastructure/dogfood/terraform/aws-tf-module/free.tf
@@ -122,12 +122,6 @@ module "ses-free" {
domain = "free.fleetdm.com"
}
-module "waf-free" {
- source = "github.com/fleetdm/fleet//terraform/addons/waf-alb?ref=tf-mod-addon-waf-alb-v1.0.0"
- name = local.customer_free
- lb_arn = module.free.byo-db.alb.lb_arn
-}
-
module "migrations_free" {
depends_on = [
module.geolite2
diff --git a/infrastructure/dogfood/terraform/aws-tf-module/main.tf b/infrastructure/dogfood/terraform/aws-tf-module/main.tf
index 8edc535bcd..2b0056fc79 100644
--- a/infrastructure/dogfood/terraform/aws-tf-module/main.tf
+++ b/infrastructure/dogfood/terraform/aws-tf-module/main.tf
@@ -397,12 +397,6 @@ module "ses" {
domain = "dogfood.fleetdm.com"
}
-module "waf" {
- source = "github.com/fleetdm/fleet//terraform/addons/waf-alb?ref=tf-mod-addon-waf-alb-v1.0.0"
- name = local.customer
- lb_arn = module.main.byo-vpc.byo-db.alb.lb_arn
-}
-
# module "saml_auth_proxy" {
# # source = "github.com/fleetdm/fleet//terraform/addons/saml-auth-proxy?ref=main"
# # public_alb_security_group_id = module.main.byo-vpc.byo-db.alb.security_group_id
From dcc28002fb79830d75de38bc9a0298d9ee2b741b Mon Sep 17 00:00:00 2001
From: Jacob Shandling <61553566+jacobshandling@users.noreply.github.com>
Date: Thu, 28 Mar 2024 11:58:08 -0700
Subject: [PATCH 24/64] =?UTF-8?q?UI=20=E2=80=93=20Fix=20alignment=20of=20a?=
=?UTF-8?q?=20filter=20on=20the=20hosts=20page=20(#17822)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## Addresses #17265
- [x] Changes file added for user-visible changes in `changes/`
- [x] Manual QA for all new/changed functionality
---------
Co-authored-by: Jacob Shandling
---
changes/17265-filter-alignment | 1 +
.../components/HostsFilterBlock/_styles.scss | 23 +++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
create mode 100644 changes/17265-filter-alignment
diff --git a/changes/17265-filter-alignment b/changes/17265-filter-alignment
new file mode 100644
index 0000000000..a27c775810
--- /dev/null
+++ b/changes/17265-filter-alignment
@@ -0,0 +1 @@
+* Fix a small alignment bug
diff --git a/frontend/pages/hosts/ManageHostsPage/components/HostsFilterBlock/_styles.scss b/frontend/pages/hosts/ManageHostsPage/components/HostsFilterBlock/_styles.scss
index 1df7fbc364..752858973b 100644
--- a/frontend/pages/hosts/ManageHostsPage/components/HostsFilterBlock/_styles.scss
+++ b/frontend/pages/hosts/ManageHostsPage/components/HostsFilterBlock/_styles.scss
@@ -15,19 +15,34 @@
// NOTE: Look more into this styling
&__os_settings-dropdown,
&__macsettings-dropdown {
- width: 137px;
-
.Select-value {
display: flex;
align-items: center;
+ position: initial !important;
+ line-height: initial !important;
&::before {
position: relative;
content: url(../assets/images/icon-filter-v2-black-16x16@2x.png);
transform: scale(0.5);
- left: -8px;
- top: 4px;
+ top: 1px;
}
}
+
+ .Select-input {
+ display: none !important;
+ }
+
+ .Select {
+ box-sizing: initial;
+ }
+
+ .Select-control {
+ height: 36px;
+ }
+
+ .dropdown__select {
+ border: 1px solid #e2e4ea;
+ }
}
}
From 9c39c6a4317c6a7b710da7c7218c096e632f683b Mon Sep 17 00:00:00 2001
From: Rachael Shaw
Date: Thu, 28 Mar 2024 14:07:42 -0500
Subject: [PATCH 25/64] Fix TCC query file names (#17941)
Accidentally gave them .yaml extension instead of .yml
---
...eries.yaml => collect-software-permissions-system.queries.yml} | 0
...queries.yaml => collect-software-permissions-user.queries.yml} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename it-and-security/lib/{collect-software-permissions-system.queries.yaml => collect-software-permissions-system.queries.yml} (100%)
rename it-and-security/lib/{collect-software-permissions-user.queries.yaml => collect-software-permissions-user.queries.yml} (100%)
diff --git a/it-and-security/lib/collect-software-permissions-system.queries.yaml b/it-and-security/lib/collect-software-permissions-system.queries.yml
similarity index 100%
rename from it-and-security/lib/collect-software-permissions-system.queries.yaml
rename to it-and-security/lib/collect-software-permissions-system.queries.yml
diff --git a/it-and-security/lib/collect-software-permissions-user.queries.yaml b/it-and-security/lib/collect-software-permissions-user.queries.yml
similarity index 100%
rename from it-and-security/lib/collect-software-permissions-user.queries.yaml
rename to it-and-security/lib/collect-software-permissions-user.queries.yml
From aabca1e40d37557a304246120d053974f679935b Mon Sep 17 00:00:00 2001
From: Roberto Dip
Date: Thu, 28 Mar 2024 16:08:59 -0300
Subject: [PATCH 26/64] lint
---
server/datastore/mysql/apple_mdm_test.go | 3 ++-
server/service/integration_ddm_test.go | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/datastore/mysql/apple_mdm_test.go b/server/datastore/mysql/apple_mdm_test.go
index 6829d32dec..c4489bcddc 100644
--- a/server/datastore/mysql/apple_mdm_test.go
+++ b/server/datastore/mysql/apple_mdm_test.go
@@ -4729,7 +4729,8 @@ func testMDMAppleDDMDeclarationsToken(t *testing.T, ds *Datastore) {
require.NotEqual(t, oldTok, toks.DeclarationsToken)
oldTok = toks.DeclarationsToken
- ds.DeleteMDMAppleConfigProfile(ctx, decl.DeclarationUUID)
+ err = ds.DeleteMDMAppleConfigProfile(ctx, decl.DeclarationUUID)
+ require.NoError(t, err)
err = ds.BulkSetPendingMDMHostProfiles(ctx, nil, nil, []string{decl2.DeclarationUUID}, nil)
require.NoError(t, err)
diff --git a/server/service/integration_ddm_test.go b/server/service/integration_ddm_test.go
index 4444649ae8..16133ade09 100644
--- a/server/service/integration_ddm_test.go
+++ b/server/service/integration_ddm_test.go
@@ -875,6 +875,7 @@ func (s *integrationMDMTestSuite) TestDDMUnsupportedDevice() {
require.NoError(t, err)
out := make(map[string]*fleet.HostMDMAppleProfile, len(profs))
for _, p := range profs {
+ p := p
out[p.Identifier] = &p
}
From dacdac904c59a5ee3bbc8598605735a699a22670 Mon Sep 17 00:00:00 2001
From: Roberto Dip
Date: Thu, 28 Mar 2024 16:57:51 -0300
Subject: [PATCH 27/64] fix test
---
server/service/integration_ddm_test.go | 35 ++++++++------------------
1 file changed, 10 insertions(+), 25 deletions(-)
diff --git a/server/service/integration_ddm_test.go b/server/service/integration_ddm_test.go
index 16133ade09..cceafd1a83 100644
--- a/server/service/integration_ddm_test.go
+++ b/server/service/integration_ddm_test.go
@@ -502,8 +502,10 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
t := s.T()
ctx := context.Background()
- addDeclaration := func(identifier string, teamID uint) string {
- fields := map[string][]string{}
+ addDeclaration := func(identifier string, teamID uint, labelNames []string) string {
+ fields := map[string][]string{
+ "labels": labelNames,
+ }
if teamID > 0 {
fields["team_id"] = []string{fmt.Sprintf("%d", teamID)}
}
@@ -599,8 +601,8 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkNoCommands(device)
// add global declarations
- d1UUID := addDeclaration("I1", 0)
- addDeclaration("I2", 0)
+ d1UUID := addDeclaration("I1", 0, nil)
+ addDeclaration("I2", 0, nil)
// reconcile again, this time new declarations were added
err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
@@ -655,8 +657,8 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkNoCommands(deviceTwo)
// add declarations to the team
- addDeclaration("I1", team.ID)
- addDeclaration("I2", team.ID)
+ addDeclaration("I1", team.ID, nil)
+ addDeclaration("I2", team.ID, nil)
// reconcile
err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
@@ -685,9 +687,6 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
checkNoCommands(deviceTwo)
checkNoCommands(deviceThree)
- // TODO: use proper APIs for this
- // add a new label + label declaration
- addDeclaration("I3", team.ID)
label, err := s.ds.NewLabel(ctx, &fleet.Label{Name: t.Name(), Query: "select 1;"})
require.NoError(t, err)
// update label with host membership
@@ -703,22 +702,8 @@ func (s *integrationMDMTestSuite) TestAppleDDMReconciliation() {
},
)
- // update declaration <-> label mapping
- mysql.ExecAdhocSQL(
- t, s.ds, func(db sqlx.ExtContext) error {
- _, err := db.ExecContext(
- context.Background(),
- `INSERT INTO
- mdm_declaration_labels (apple_declaration_uuid, label_name, label_id)
- VALUES ((SELECT declaration_uuid FROM mdm_apple_declarations WHERE team_id = ? and identifier = ?), ?, ?)`,
- team.ID,
- "I3",
- label.Name,
- label.ID,
- )
- return err
- },
- )
+ // add a new label + label declaration
+ addDeclaration("I3", team.ID, []string{label.Name})
// reconcile
err = ReconcileAppleDeclarations(ctx, s.ds, s.mdmCommander, s.logger)
From 7867ec98ab5a4863d6b0fea1cef62b8115575020 Mon Sep 17 00:00:00 2001
From: Eric
Date: Thu, 28 Mar 2024 15:26:12 -0500
Subject: [PATCH 28/64] Website: update header navigation links on admin pages
(#17947)
Closes: #17943
Changes:
- Updated the styles and layout of admin links that are visible on admin
pages.
---
website/assets/styles/layout.less | 29 +++++++++++++++--------------
website/views/layouts/layout.ejs | 19 +++++++++++++------
2 files changed, 28 insertions(+), 20 deletions(-)
diff --git a/website/assets/styles/layout.less b/website/assets/styles/layout.less
index 42b4574d6b..210cc4914b 100644
--- a/website/assets/styles/layout.less
+++ b/website/assets/styles/layout.less
@@ -304,22 +304,23 @@ html, body {
}
}
}
- [purpose='admin-nav'] {
- justify-content: center;
- a {
- margin-left: 30px;
- margin-right: 30px;
- color: @core-fleet-black-75;
- &:hover {
- color: @core-fleet-black;
- }
- }
- span {
- color: @core-fleet-black;
- font-weight: 600;
- margin-right: 30px;
+}
+[purpose='admin-nav'] {
+ justify-content: center;
+
+ [purpose='admin-link'] {
+ margin-left: 30px;
+ margin-right: 30px;
+ color: @core-fleet-black-75;
+ &:hover {
+ color: @core-vibrant-blue;
}
}
+ span {
+ color: @core-fleet-black;
+ font-weight: 600;
+ margin-right: 30px;
+ }
}
// Footer styles
diff --git a/website/views/layouts/layout.ejs b/website/views/layouts/layout.ejs
index 6ec8255421..0d069e0dac 100644
--- a/website/views/layouts/layout.ejs
+++ b/website/views/layouts/layout.ejs
@@ -207,8 +207,16 @@
Pricing
<% if(_.has(me, 'id')) {%>
- Log out
+ Log out
<% }%>
+ <%if(me && me.isSuperAdmin && showAdminLinks) {%>
+
+ Admin
+
+ <%}%>
Talk to us
@@ -275,14 +283,13 @@
<% } %>
<%if(me && me.isSuperAdmin && showAdminLinks) {%>
-
+
Admin pages
-
<%} %>
From 456b546256a4a371397039c9df3f42af845c123c Mon Sep 17 00:00:00 2001
From: Mike McNeil
Date: Fri, 29 Mar 2024 07:04:09 -0700
Subject: [PATCH 29/64] Increase default credit card limit (#17937)
Up to @JoStableford
Co-authored-by: Joanne Stableford <59930035+JoStableford@users.noreply.github.com>
---
handbook/company/communications.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/handbook/company/communications.md b/handbook/company/communications.md
index bc96271f7f..5df7633ba2 100644
--- a/handbook/company/communications.md
+++ b/handbook/company/communications.md
@@ -395,7 +395,7 @@ For more developed thoughts about __spending guidelines and limits__, please rea
### Brex
#### Non-travel purchases that exceed a Brex cardholder's limit
-For non-travel purchases that would require an increase in the Brex cardholder's limit, please [make a request](https://fleetdm.com/handbook/business-operations#contact-us) with following information:
+For non-travel purchases that would require an increase in the Brex cardholder's limit ($2,000 by default), please [make a request](https://fleetdm.com/handbook/business-operations#contact-us) with following information:
- The nature of the purchase (i.e. SaaS subscription and what it's used for)
- The cost of the purchase and whether it is a fixed or variable (i.e. use-based) cost.
- Whether it is a one time purchase or a recurring purchase and at what frequency the purchase will re-occur (annually, monthly, etc.)
From ea874bc13471b3214bf545ad9e75038a1acf1efb Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Fri, 29 Mar 2024 10:38:13 -0400
Subject: [PATCH 30/64] [styling bug] Fleet UI: Update live query disabled
warning styling (#17929)
---
...ix-styling-for-live-query-disabled-warning | 1 +
frontend/pages/queries/edit/EditQueryPage.tsx | 29 +++++++++----------
frontend/pages/queries/edit/_styles.scss | 16 ----------
3 files changed, 14 insertions(+), 32 deletions(-)
create mode 100644 changes/17927-fix-styling-for-live-query-disabled-warning
diff --git a/changes/17927-fix-styling-for-live-query-disabled-warning b/changes/17927-fix-styling-for-live-query-disabled-warning
new file mode 100644
index 0000000000..42323137fb
--- /dev/null
+++ b/changes/17927-fix-styling-for-live-query-disabled-warning
@@ -0,0 +1 @@
+- UI fix: styling of live query disabled warning
diff --git a/frontend/pages/queries/edit/EditQueryPage.tsx b/frontend/pages/queries/edit/EditQueryPage.tsx
index 92e5e7dc9f..8d88cc53b3 100644
--- a/frontend/pages/queries/edit/EditQueryPage.tsx
+++ b/frontend/pages/queries/edit/EditQueryPage.tsx
@@ -14,11 +14,14 @@ import {
ICreateQueryRequestBody,
ISchedulableQuery,
} from "interfaces/schedulable_query";
+import { IConfig } from "interfaces/config";
import QuerySidePanel from "components/side_panels/QuerySidePanel";
import MainContent from "components/MainContent";
import SidePanelContent from "components/SidePanelContent";
import CustomLink from "components/CustomLink";
+import BackLink from "components/BackLink";
+import InfoBanner from "components/InfoBanner";
import useTeamIdParam from "hooks/useTeamIdParam";
@@ -28,9 +31,7 @@ import PATHS from "router/paths";
import debounce from "utilities/debounce";
import deepDifference from "utilities/deep_difference";
-import BackLink from "components/BackLink";
-import EditQueryForm from "pages/queries/edit/components/EditQueryForm";
-import { IConfig } from "interfaces/config";
+import EditQueryForm from "./components/EditQueryForm";
interface IEditQueryPageProps {
router: InjectedRouter;
@@ -304,19 +305,15 @@ const EditQueryPage = ({
}
return (
-
-
-
- Fleet is unable to run a live query. Refresh the page or log in
- again. If this keeps happening please{" "}
-
-
-
-
+
+ Fleet is unable to run a live query. Refresh the page or log in again.
+ If this keeps happening please{" "}
+
+
);
};
diff --git a/frontend/pages/queries/edit/_styles.scss b/frontend/pages/queries/edit/_styles.scss
index e1523d2dfb..dec949a167 100644
--- a/frontend/pages/queries/edit/_styles.scss
+++ b/frontend/pages/queries/edit/_styles.scss
@@ -1,22 +1,6 @@
.edit-query-page {
@include page;
- &__warning {
- padding: $pad-medium;
- font-size: $x-small;
- color: $core-fleet-black;
- background-color: #fff0b9;
- border: 1px solid #f2c94c;
- border-radius: $border-radius;
- margin: 0;
- margin-top: $pad-large;
-
- p {
- margin: 0;
- line-height: 20px;
- }
- }
-
.ace_content {
min-height: 500px !important;
}
From 75ef2c0efae82c1f808cd5bd60ec4e9f86906864 Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Fri, 29 Mar 2024 10:39:20 -0400
Subject: [PATCH 31/64] New yarn configuration: Sets installing a dependency to
a specific semantic versioning instead of latest stable (#17938)
---
.yarnrc | 1 +
1 file changed, 1 insertion(+)
create mode 100644 .yarnrc
diff --git a/.yarnrc b/.yarnrc
new file mode 100644
index 0000000000..fdd705c635
--- /dev/null
+++ b/.yarnrc
@@ -0,0 +1 @@
+save-prefix ""
From bb0d031ea895bc39978243133d4d59a38ef93533 Mon Sep 17 00:00:00 2001
From: Sarah Gillespie <73313222+gillespi314@users.noreply.github.com>
Date: Fri, 29 Mar 2024 09:48:31 -0500
Subject: [PATCH 32/64] Populate `host.MDMInfo` when getting host details for
Windows host (#17893)
---
cmd/fleetctl/mdm_test.go | 38 +++++++++++++++++++
server/datastore/mysql/microsoft_mdm.go | 22 ++++++-----
server/datastore/mysql/microsoft_mdm_test.go | 4 ++
server/service/hosts.go | 39 +++++++++++++++++---
server/service/hosts_test.go | 16 +++++++-
server/service/integration_mdm_test.go | 8 ++++
6 files changed, 112 insertions(+), 15 deletions(-)
diff --git a/cmd/fleetctl/mdm_test.go b/cmd/fleetctl/mdm_test.go
index d275e15aab..0a7062de30 100644
--- a/cmd/fleetctl/mdm_test.go
+++ b/cmd/fleetctl/mdm_test.go
@@ -101,8 +101,10 @@ func TestMDMRunCommand(t *testing.T) {
MDM: fleet.MDMHostData{Name: fleet.WellKnownMDMFleet, EnrollmentStatus: ptr.String("Pending")},
}
hostByUUID := make(map[string]*fleet.Host)
+ hostByID := make(map[uint]*fleet.Host)
for _, h := range []*fleet.Host{macEnrolled, winEnrolled, macUnenrolled, winUnenrolled, linuxUnenrolled, macEnrolled2, winEnrolled2, macNonFleetEnrolled, winNonFleetEnrolled, macPending, winPending} {
hostByUUID[h.UUID] = h
+ hostByID[h.ID] = h
}
// define some files to use in the tests
@@ -221,6 +223,15 @@ func TestMDMRunCommand(t *testing.T) {
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
return &fleet.HostMDMDiskEncryption{}, nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostByID[hostID]
+ require.True(t, ok)
+ if h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+ return h.MDMInfo, nil
+ }
+
enqueuer.EnqueueCommandFunc = func(ctx context.Context, id []string, cmd *mdm.Command) (map[string]error, error) {
return map[string]error{}, nil
}
@@ -467,6 +478,15 @@ func TestMDMLockCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
@@ -701,6 +721,15 @@ func TestMDMUnlockCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
successfulOutput := func(ident string) string {
@@ -1001,6 +1030,15 @@ func TestMDMWipeCommand(t *testing.T) {
return nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ h, ok := hostsByID[hostID]
+ if !ok || h.MDMInfo == nil {
+ return nil, ¬FoundError{}
+ }
+
+ return h.MDMInfo, nil
+ }
+
appCfgAllMDM, appCfgWinMDM, appCfgMacMDM, appCfgNoMDM := setupAppConigs()
appCfgScriptsDisabled := &fleet.AppConfig{ServerSettings: fleet.ServerSettings{ScriptsDisabled: true}}
diff --git a/server/datastore/mysql/microsoft_mdm.go b/server/datastore/mysql/microsoft_mdm.go
index e8904bb5a9..3380815902 100644
--- a/server/datastore/mysql/microsoft_mdm.go
+++ b/server/datastore/mysql/microsoft_mdm.go
@@ -633,17 +633,20 @@ WHERE
func (ds *Datastore) GetMDMWindowsBitLockerStatus(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
if host == nil {
- return nil, errors.New("host cannot be nil")
+ return nil, ctxerr.New(ctx, "cannot get bitlocker status for nil host")
}
if host.Platform != "windows" {
- // Generally, the caller should have already checked this, but just in case we log and
- // return nil
- level.Debug(ds.logger).Log("msg", "cannot get bitlocker status for non-windows host", "host_id", host.ID)
- return nil, nil
+ // the caller should have already checked this
+ return nil, ctxerr.Errorf(ctx, "cannot get bitlocker status for non-windows host %d", host.ID)
}
- if host.MDMInfo != nil && host.MDMInfo.IsServer {
+ if host.MDMInfo == nil {
+ // the caller should have already checked
+ return nil, ctxerr.Errorf(ctx, "cannot get bitlocker status because no mdm info for host %d", host.ID)
+ }
+
+ if host.MDMInfo.IsServer {
// It is currently expected that server hosts do not have a bitlocker status so we can skip
// the query and return nil. We log for potential debugging in case this changes in the future.
level.Debug(ds.logger).Log("msg", "no bitlocker status for server host", "host_id", host.ID)
@@ -700,9 +703,10 @@ WHERE
}
if dest.Status == "" {
- // If we have no status, we treat it as enforcing since we know disk encryption is enabled and log for potential debugging
- level.Debug(ds.logger).Log("msg", "no bitlocker status found for host", "host_id", host.ID)
- dest.Status = fleet.DiskEncryptionEnforcing
+ // This is unexpected. We know that disk encryption is enabled so we treat it failed to draw
+ // attention to the issue and log potential debugging
+ level.Debug(ds.logger).Log("msg", "no bitlocker status found for host", "host_id", host.ID, "mdm_info", fmt.Sprintf("%+v", host.MDMInfo))
+ dest.Status = fleet.DiskEncryptionFailed
}
return &fleet.HostMDMDiskEncryption{
diff --git a/server/datastore/mysql/microsoft_mdm_test.go b/server/datastore/mysql/microsoft_mdm_test.go
index dff2c124ea..6a7be91fd3 100644
--- a/server/datastore/mysql/microsoft_mdm_test.go
+++ b/server/datastore/mysql/microsoft_mdm_test.go
@@ -157,6 +157,10 @@ func testMDMWindowsDiskEncryption(t *testing.T, ds *Datastore) {
h, err := ds.Host(ctx, id)
require.NoError(t, err)
require.NotNil(t, h)
+ mdmInfo, err := ds.GetHostMDM(ctx, id)
+ require.NoError(t, err)
+ require.NotNil(t, mdmInfo)
+ h.MDMInfo = mdmInfo
bls, err := ds.GetMDMWindowsBitLockerStatus(ctx, h)
require.NoError(t, err)
require.NotNil(t, bls)
diff --git a/server/service/hosts.go b/server/service/hosts.go
index 2591df1274..14b7bb7119 100644
--- a/server/service/hosts.go
+++ b/server/service/hosts.go
@@ -24,6 +24,7 @@ import (
"github.com/fleetdm/fleet/v4/server/mdm/apple/mobileconfig"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/worker"
+ "github.com/go-kit/kit/log/level"
"github.com/gocarina/gocsv"
)
@@ -1029,17 +1030,30 @@ func (svc *Service) getHostDetails(ctx context.Context, host *fleet.Host, opts f
if !ac.MDM.WindowsEnabledAndConfigured {
break
}
+
if license.IsPremium(ctx) {
- hde, err := svc.ds.GetMDMWindowsBitLockerStatus(ctx, host)
+ // we include disk encryption status only for premium so initialize it to default struct
+ host.MDM.OSSettings.DiskEncryption = fleet.HostMDMDiskEncryption{}
+ // ensure host mdm info is loaded (we don't know if our caller populated it)
+ err := svc.ensureHostMDMInfo(ctx, host)
switch {
+ case err != nil && fleet.IsNotFound(err):
+ // assume host is unmanaged, log for debugging, and move on
+ level.Debug(svc.logger).Log("msg", "cannot determine bitlocker status because no mdm info for host", "host_id", host.ID)
case err != nil:
- return nil, ctxerr.Wrap(ctx, err, "get host mdm bitlocker status")
- case hde != nil:
- host.MDM.OSSettings.DiskEncryption = *hde
+ return nil, ctxerr.Wrap(ctx, err, "ensure host mdm info")
default:
- host.MDM.OSSettings.DiskEncryption = fleet.HostMDMDiskEncryption{}
+ hde, err := svc.ds.GetMDMWindowsBitLockerStatus(ctx, host)
+ if err != nil {
+ return nil, ctxerr.Wrap(ctx, err, "get host mdm bitlocker status")
+ }
+ if hde != nil {
+ // overwrite the default disk encryption status
+ host.MDM.OSSettings.DiskEncryption = *hde
+ }
}
}
+
profs, err := svc.ds.GetHostMDMWindowsProfiles(ctx, host.UUID)
if err != nil {
return nil, ctxerr.Wrap(ctx, err, "get host mdm windows profiles")
@@ -1124,6 +1138,21 @@ func (svc *Service) getHostDetails(ctx context.Context, host *fleet.Host, opts f
}, nil
}
+func (svc *Service) ensureHostMDMInfo(ctx context.Context, host *fleet.Host) error {
+ if host.MDMInfo == nil {
+ mdmInfo, err := svc.ds.GetHostMDM(ctx, host.ID)
+ if err != nil {
+ return err
+ }
+ host.MDMInfo = mdmInfo
+ }
+ if host.MDMInfo == nil {
+ // this should not happen, but just in case
+ return ctxerr.New(ctx, fmt.Sprintf("nil mdm info for host %d", host.ID))
+ }
+ return nil
+}
+
////////////////////////////////////////////////////////////////////////////////
// Get Host Query Report
////////////////////////////////////////////////////////////////////////////////
diff --git a/server/service/hosts_test.go b/server/service/hosts_test.go
index 4358399ebc..b2480bf3ab 100644
--- a/server/service/hosts_test.go
+++ b/server/service/hosts_test.go
@@ -407,6 +407,7 @@ func TestHostDetailsOSSettings(t *testing.T) {
ds.GetMDMWindowsBitLockerStatusFuncInvoked = false
ds.GetHostMDMAppleProfilesFuncInvoked = false
ds.GetHostMDMWindowsProfilesFuncInvoked = false
+ ds.GetHostMDMFuncInvoked = false
ds.AppConfigFunc = func(ctx context.Context) (*fleet.AppConfig, error) {
return &fleet.AppConfig{MDM: fleet.MDM{EnabledAndConfigured: true, WindowsEnabledAndConfigured: true}}, nil
@@ -423,6 +424,10 @@ func TestHostDetailsOSSettings(t *testing.T) {
ds.GetHostMDMWindowsProfilesFunc = func(ctx context.Context, uuid string) ([]fleet.HostMDMWindowsProfile, error) {
return nil, nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ hmdm := fleet.HostMDM{Enrolled: true, IsServer: false}
+ return &hmdm, nil
+ }
}
for _, c := range cases {
@@ -442,6 +447,11 @@ func TestHostDetailsOSSettings(t *testing.T) {
switch c.host.Platform {
case "windows":
require.False(t, ds.GetHostMDMAppleProfilesFuncInvoked)
+ if c.licenseTier == fleet.TierPremium {
+ require.True(t, ds.GetHostMDMFuncInvoked)
+ } else {
+ require.False(t, ds.GetHostMDMFuncInvoked)
+ }
if c.wantStatus != "" {
require.True(t, ds.GetMDMWindowsBitLockerStatusFuncInvoked)
require.NotNil(t, hostDetail.MDM.OSSettings.DiskEncryption.Status)
@@ -500,6 +510,10 @@ func TestHostDetailsOSSettingsWindowsOnly(t *testing.T) {
ds.GetHostLockWipeStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostLockWipeStatus, error) {
return &fleet.HostLockWipeStatus{}, nil
}
+ ds.GetHostMDMFunc = func(ctx context.Context, hostID uint) (*fleet.HostMDM, error) {
+ hmdm := fleet.HostMDM{Enrolled: true, IsServer: false}
+ return &hmdm, nil
+ }
ctx := license.NewContext(context.Background(), &fleet.LicenseInfo{Tier: fleet.TierPremium})
hostDetail, err := svc.getHostDetails(test.UserContext(ctx, test.UserAdmin), &fleet.Host{ID: 42, Platform: "windows"}, fleet.HostDetailOptions{
@@ -510,6 +524,7 @@ func TestHostDetailsOSSettingsWindowsOnly(t *testing.T) {
require.NotNil(t, hostDetail)
require.True(t, ds.AppConfigFuncInvoked)
require.False(t, ds.GetHostMDMAppleProfilesFuncInvoked)
+ require.True(t, ds.GetHostMDMFuncInvoked)
require.True(t, ds.GetMDMWindowsBitLockerStatusFuncInvoked)
require.NotNil(t, hostDetail.MDM.OSSettings.DiskEncryption.Status)
require.Equal(t, fleet.DiskEncryptionVerified, *hostDetail.MDM.OSSettings.DiskEncryption.Status)
@@ -1500,7 +1515,6 @@ func TestLockUnlockWipeHostAuth(t *testing.T) {
if hostID == teamHostID {
return teamHost, nil
}
-
return globalHost, nil
}
ds.GetMDMWindowsBitLockerStatusFunc = func(ctx context.Context, host *fleet.Host) (*fleet.HostMDMDiskEncryption, error) {
diff --git a/server/service/integration_mdm_test.go b/server/service/integration_mdm_test.go
index 4b6bbfc23f..d026d849d8 100644
--- a/server/service/integration_mdm_test.go
+++ b/server/service/integration_mdm_test.go
@@ -12063,6 +12063,14 @@ func (s *integrationMDMTestSuite) TestIsServerBitlockerStatus() {
var hr getHostResponse
s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d", host.ID), nil, http.StatusOK, &hr)
+ require.Nil(t, hr.Host.MDM.OSSettings.DiskEncryption.Status)
+ // create a non-server host that is enrolled in MDM
+ host2 := createOrbitEnrolledHost(t, "windows", "non-server-host", s.ds)
+ require.NoError(t, s.ds.SetOrUpdateMDMData(ctx, host2.ID, false, true, "http://example.com", false, fleet.WellKnownMDMFleet, ""))
+
+ hr = getHostResponse{}
+ s.DoJSON("GET", fmt.Sprintf("/api/latest/fleet/hosts/%d", host2.ID), nil, http.StatusOK, &hr)
+ require.NotNil(t, hr.Host.MDM.OSSettings.DiskEncryption.Status)
require.Equal(t, fleet.DiskEncryptionEnforcing, *hr.Host.MDM.OSSettings.DiskEncryption.Status)
}
From 1833e1fc5b136bd5c900f6740d2686cffd4a3cad Mon Sep 17 00:00:00 2001
From: Lucas Manuel Rodriguez
Date: Fri, 29 Mar 2024 12:17:52 -0300
Subject: [PATCH 33/64] Reset query report when
`platform`/`min_osquery_version` is changed (#17847)
#17018
- [X] Changes file added for user-visible changes in `changes/` or
`orbit/changes/`.
See [Changes
files](https://fleetdm.com/docs/contributing/committing-changes#changes-files)
for more information.
- [X] Added/updated tests
- [X] Manual QA for all new/changed functionality
---------
Co-authored-by: RachelElysia
Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
---
changes/17018-reset-query-report | 1 +
.../EditQueryForm/EditQueryForm.tsx | 23 ++-
server/service/integration_core_test.go | 138 +++++++++++++++++-
server/service/queries.go | 26 +++-
server/service/queries_test.go | 63 ++++++++
5 files changed, 247 insertions(+), 4 deletions(-)
create mode 100644 changes/17018-reset-query-report
diff --git a/changes/17018-reset-query-report b/changes/17018-reset-query-report
new file mode 100644
index 0000000000..444fac3f8b
--- /dev/null
+++ b/changes/17018-reset-query-report
@@ -0,0 +1 @@
+- Query report is reset when there is a change to the selected platform or selected minimum osquery version
diff --git a/frontend/pages/queries/edit/components/EditQueryForm/EditQueryForm.tsx b/frontend/pages/queries/edit/components/EditQueryForm/EditQueryForm.tsx
index c5b70d70a9..5fc45797b8 100644
--- a/frontend/pages/queries/edit/components/EditQueryForm/EditQueryForm.tsx
+++ b/frontend/pages/queries/edit/components/EditQueryForm/EditQueryForm.tsx
@@ -638,12 +638,32 @@ const EditQueryForm = ({
"differential_ignore_removals",
].includes(lastEditedQueryLoggingType);
+ // Note: The backend is not resetting the query reports with equivalent platform strings
+ // so we are not showing a warning unless the platform combinations differ
+ const formatPlatformEquivalences = (platforms?: string) => {
+ // Remove white spaces allowed by API and format into a sorted string converted from a sorted array
+ return platforms?.replace(/\s/g, "").split(",").sort().toString();
+ };
+
+ const changedPlatforms =
+ storedQuery &&
+ formatPlatformEquivalences(lastEditedQueryPlatforms) !==
+ formatPlatformEquivalences(storedQuery?.platform);
+
+ const changedMinOsqueryVersion =
+ storedQuery &&
+ lastEditedQueryMinOsqueryVersion !== storedQuery.min_osquery_version;
+
const enabledDiscardData =
storedQuery && lastEditedQueryDiscardData && !storedQuery.discard_data;
const confirmChanges =
currentlySavingQueryResults &&
- (changedSQL || changedLoggingToDifferential || enabledDiscardData);
+ (changedSQL ||
+ changedLoggingToDifferential ||
+ enabledDiscardData ||
+ changedPlatforms ||
+ changedMinOsqueryVersion);
const showChangedSQLCopy =
changedSQL && !changedLoggingToDifferential && !enabledDiscardData;
@@ -660,6 +680,7 @@ const EditQueryForm = ({
const disableSaveFormErrors =
(lastEditedQueryName === "" && !!lastEditedQueryId) || !!size(errors);
+ console.log("lastEditedQueryPlatforms", lastEditedQueryPlatforms);
return (
<>