From 860dcf2609e2b25a6d6becf8006a7118a19cd615 Mon Sep 17 00:00:00 2001 From: Rachael Shaw Date: Thu, 18 Jan 2024 16:37:47 -0600 Subject: [PATCH] Best practice GitOps file structure (#17) * Best practice GH action - WIP * Finish stubbing out action (requires changes to fleetctl) * A few changes to stubbed-out action for readability * Best practice GitOps example with query and policy libraries * Update macos-workstations.policies.yml * Update README.md * --replace instead of --force (--force already existed for skipping validation) * Update action.yml * Update cis.policies.yml - Link to CIS policies * Move /queries and /policies contents to /lib * Update best practice * Add policies and queries * Add macOS' * Only start w/ controls, queries, and policies * Update device health policies * Cut a policy * Sentence casing and update name of Remote Application Scripting * Sentence case * Sentence case * Remove --- from teams * Separate files * Changes during the call * Changes during the call * Observers can't run * change policy * Changes from the call * Prep for call * Reorg * reorg * Prep for call * Changes from the call * Update * Validate YAML * Update README * Update README * Fleet GitOps is in beta * Update language in README to clarify the status of this repo (So we can go ahead and merge the PR with the best practice file structure) * Update README.md --------- Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com> Co-authored-by: Noah Talerman --- .DS_Store | Bin 0 -> 6148 bytes .github/workflows/workflow.yml | 100 +++++++ CODEOWNERS | 3 - README.md | 46 ++-- action.yml | 75 ------ best-practice/README.md | 22 -- best-practice/default.policies.yml | 11 - best-practice/default.queries.yml | 10 - best-practice/default.settings.yml | 144 ---------- best-practice/no-team.controls.yml | 13 - default.yml | 54 ++++ example-workflow.yml | 44 --- lib/agent-options.yml | 13 + ...collect-failed-login-attempts.queryies.yml | 6 + lib/collect-fleetd-logs.sh | 7 + ...collect-fleetd-update-channels.queries.yml | 6 + lib/collect-usb-devices.queries.yml | 6 + lib/device-health.policies.yml | 250 ++++++++++++++++++ lib/macos-os-updates.ddm.json | 10 + lib/macos-password.mobileconfig | 55 ++++ .../remove-zoom-artifacts.script.sh | 0 .../set-timezone.script.sh | 0 .../uninstall-zoom.script.sh | 0 lib/windows-screenlock.xml | 48 ++++ teams/workstations-canary.yml | 45 ++++ teams/workstations.yml | 44 +++ 26 files changed, 659 insertions(+), 353 deletions(-) create mode 100644 .DS_Store create mode 100644 .github/workflows/workflow.yml delete mode 100644 CODEOWNERS delete mode 100644 action.yml delete mode 100644 best-practice/README.md delete mode 100644 best-practice/default.policies.yml delete mode 100644 best-practice/default.queries.yml delete mode 100644 best-practice/default.settings.yml delete mode 100644 best-practice/no-team.controls.yml create mode 100644 default.yml delete mode 100644 example-workflow.yml create mode 100644 lib/agent-options.yml create mode 100644 lib/collect-failed-login-attempts.queryies.yml create mode 100644 lib/collect-fleetd-logs.sh create mode 100644 lib/collect-fleetd-update-channels.queries.yml create mode 100644 lib/collect-usb-devices.queries.yml create mode 100644 lib/device-health.policies.yml create mode 100644 lib/macos-os-updates.ddm.json create mode 100644 lib/macos-password.mobileconfig rename best-practice/scripts/remove-zoom-artifacts.sh => lib/remove-zoom-artifacts.script.sh (100%) rename best-practice/scripts/set-timezone.sh => lib/set-timezone.script.sh (100%) rename best-practice/scripts/uninstall-zoom.sh => lib/uninstall-zoom.script.sh (100%) create mode 100644 lib/windows-screenlock.xml create mode 100644 teams/workstations-canary.yml create mode 100644 teams/workstations.yml diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4d898266618d9a19dae7c5bf19ec406a2f35c034 GIT binary patch literal 6148 zcmeHK%Wl&^6ur|1;-spSMUlFxWU1RUgcemq-Iz34u%Jjaq6HL&_M z*7eetqV}Bg*uRZE|3wrQgT~G&PjW9x!c-EXAjFVY7f}-MqRS^qkV&qqI;@&i8#H#O z)5Fej(?04vnlgDq|6yxujn-tAViYh6{2c|v{$RreIvPub za_c}LuK>Ubnx!EYp9_LxYjiZ03ef{&iV9Rzrmq-G(a~<}agN4Pp`sJhmk*|AX8MN0 z%AvTUQn*&RQG( s1};pDD-}u#3Vj^QKpe%paB1kXMF4a(mI~1VGamv{22&UX{;2}r0c8W2N&o-= literal 0 HcmV?d00001 diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml new file mode 100644 index 0000000..047479a --- /dev/null +++ b/.github/workflows/workflow.yml @@ -0,0 +1,100 @@ +name: 'Apply latest configuration profiles via Fleet' +description: 'Applies the latest MDM configuration profiles to a Fleet team' + +inputs: + FLEET_API_TOKEN: + description: 'Fleet API Token' + required: true + FLEET_URL: + description: 'Fleet URL' + required: true + +runs: + using: 'composite' + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + repository: ${{ inputs.MDM_CONFIG_REPO }} + + - name: Install fleetctl + run: npm install -g fleetctl + shell: bash + + - name: Configure fleetctl + run: fleetctl config set --address ${{ inputs.FLEET_URL }} --token ${{ inputs.FLEET_API_TOKEN }} + shell: bash + + - name: Run fleetctl apply + run: | + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # STEP 1: Apply config + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Combine the contents of all the top-level config into a single YAML document + + # - Include the contents of no-team.controls.yml + # TODO + + # - Include the contents of default.settings.yml + # TODO + + # - Include anything of `kind: config` in default.queries.yml + # TODO + + # - Include anything of `kind: config` in default.policies.yml + # TODO + + # Apply top-level config with `--replace` (replaces all existing top-level config) + # TODO + + # Loop through folders in /teams and combine the contents of all team config into a single YAML document + + # - Include the contents of .controls.yml + # TODO + + # - Include the contents of .settings.yml + # TODO + + # - Include anything of `kind: team` in .queries.yml + # TODO + + # - Include anything of `kind: team` in .policies.yml + # TODO + + # Apply team config with `--replace` (replaces all existing config for this team) + # TODO + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # STEP 2: Apply queries + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Compile all queries into a single YAML document + + # - Include anything of `kind: query` in default.queries.yml + # TODO + + # - Loop through folders in /teams and include anything of `kind: query` in .queries.yml for each + # TODO + + # Apply compiled queries YAML with `--replace` (deletes any queries in Fleet that aren't present in this config) + # TODO + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # STEP 3: Apply policies + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # Compile all policies into a single YAML document + # TODO + + # - Include anything of `kind: policy` in default.policies.yml + # TODO + + # - Loop through folders in /teams and include anything of `kind: policy` in .policies.yml for each + # TODO + + # Apply compiled policies YAML with `--replace` (deletes any policies in Fleet that aren't present in this config) + # TODO + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + # All done! + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + shell: bash diff --git a/CODEOWNERS b/CODEOWNERS deleted file mode 100644 index fa1fcf3..0000000 --- a/CODEOWNERS +++ /dev/null @@ -1,3 +0,0 @@ -# Action owner -* @lukeheath - diff --git a/README.md b/README.md index 7c64553..6ba415b 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,24 @@ -# fleet-mdm-gitops -This GitHub Action applies the latest MDM configuration profiles to a group of hosts in [Fleet](https://fleetdm.com). It lets everyone contribute, while giving you history and an approval workflow. +# Fleet GitOps -![image](https://github.com/fleetdm/fleet-mdm-gitops/assets/618009/83cb87b6-2303-40e4-bc5b-e0f8168a00c7) +> #### 🚧 Fleet GitOps is currently in development. +> +> In the mean time, you can explore this repo for a preview of Fleet's GitOps best practice, and track its progress [here](https://github.com/fleetdm/fleet/issues/13643). -## Example usage +This folder illustrates the best practice for using Fleet with a GitOps workflow. -```yml -steps: - - name: Apply configuration profiles and updates - uses: fleetdm/fleet-mdm-gitops - with: - FLEET_API_TOKEN: ${{ secrets.FLEET_API_TOKEN }} - FLEET_URL: ${{ secrets.FLEET_URL }} - FLEET_TEAM_NAME: Workstations - MDM_CONFIG_REPO: fleetdm/fleet - MDM_CONFIG_DIRECTORY: mdm_profiles - MAC_OS_MIN_VERSION: 13.3.1 - MAC_OS_VERSION_DEADLINE: 2023-05-15 - MAC_OS_ENABLE_DISK_ENCRYPTION: true -``` +How to setup a GitOps workflow to manage Fleet: +1. Clone this repository. -## Contributing +2. Make any changes to policies, queries, controls, and more defined in the files. -Please observe the guidelines and conventions laid out in the [Fleet contribution guide](https://fleetdm.com/) when opening issues or submitting pull requests. +3. Create your own GitHub repository and push your cloned and modified code to your repo. -### Help +4. Add Fleet's open-source [GitHub action](https://github.com/fleetdm/fleet-gitops) to your repo. Now, when anyone makes a change to any file, the action will run and update Fleet. -Unsure? If you run into any trouble or questions, click [here](https://fleetdm.com/slack). +#### Structure: - -### Bugs - -If you suspect you've found a bug, please [report the bug here](https://github.com/fleetdm/fleet/issues). Thanks! - - -## License - -This GitHub Action is free and open-source under the MIT License. +- `lib/` - folder for policies, queries, configuration profiles, scripts, and agent options. These files can be referenced in top level keys in the `default.yml` file and the files in the `teams/` folder. +- `default.yml` - file that defines the queries, policies, controls, and agent options for all hosts. If you're using Fleet Premium, this file updates queries and policies that run on all hosts ("All teams"). Controls and agent options are defined for hosts on "No team." +- `teams/` - folder for teams in Fleet. These files define the controls, queries, policies, and agent options for hosts assigned to the specified team. +- `.github/workflows/workflow.yml` - TODO: Explain how to add/update secrets. That's what this file is used for diff --git a/action.yml b/action.yml deleted file mode 100644 index bc81f44..0000000 --- a/action.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: 'Apply latest configuration profiles via Fleet' -description: 'Applies the latest MDM configuration profiles to a Fleet team' - -inputs: - FLEET_API_TOKEN: - description: 'Fleet API Token' - required: true - FLEET_URL: - description: 'Fleet URL' - required: true - FLEET_TEAM_NAME: - description: 'Fleet team name to apply MDM configuration profiles to' - required: true - default: "Workstations" - MDM_CONFIG_REPO: - description: 'Repository containing MDM configuration profiles' - required: true - default: 'fleetdm/fleet' - MDM_CONFIG_DIRECTORY: - description: 'Directory in repo where MDM configuration files are stored' - required: true - default: 'mdm_profiles' - MAC_OS_MIN_VERSION: - description: 'Minimum macOS version of hosts' - required: true - MAC_OS_VERSION_DEADLINE: - description: 'Deadline for macOS version' - required: true - MAC_OS_ENABLE_DISK_ENCRYPTION: - description: 'Enable disk encryption' - required: true - default: 'true' - -runs: - using: 'composite' - steps: - - name: Checkout code - uses: actions/checkout@v3 - with: - repository: ${{ inputs.MDM_CONFIG_REPO }} - - - name: Install fleetctl - run: npm install -g fleetctl - shell: bash - - - name: Configure fleetctl - run: fleetctl config set --address ${{ inputs.FLEET_URL }} --token ${{ inputs.FLEET_API_TOKEN }} - shell: bash - - - name: Run fleetctl apply - run: | - profiles="" - - for file in ${{ inputs.MDM_CONFIG_DIRECTORY }}/*.mobileconfig; do - envsubst < "$file" > "${file}.new" - mv "${file}.new" "$file" - profiles+=$' - '$file$'\n' - done - - echo "apiVersion: v1 - kind: team - spec: - team: - name: ${{ inputs.FLEET_TEAM_NAME }} - mdm: - macos_updates: - minimum_version: \"${{ inputs.MAC_OS_MIN_VERSION }}\" - deadline: ${{ inputs.MAC_OS_VERSION_DEADLINE }} - macos_settings: - enable_disk_encryption: ${{ inputs.MAC_OS_ENABLE_DISK_ENCRYPTION }} - custom_settings: - $profiles - " > team-workstations-config.yml - fleetctl apply -f team-workstations-config.yml - shell: bash diff --git a/best-practice/README.md b/best-practice/README.md deleted file mode 100644 index a2366c1..0000000 --- a/best-practice/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Best practice - -This folder illustrates the best practice for using Fleet with a GitOps workflow. - -Soon, a Fleet user will be able to clone this repository, push up the contents of this `best-practice/` folder to their organization's repository, and add Fleet's open-source [GitHub action](https://github.com/fleetdm/fleet-mdm-gitops) to the repo. When the user makes changes to any file, the action will run and update Fleet. - -> The GitHub action is not ready for use with this best practice. The action only supports configuration profiles, disk encryption and OS updates for macOS. - -#### Structure: - -- `mdm-profiles` - folder for configuration profiles. These profiles are referenced in `no-team.controls.yml` and team level `controls.yml`. -- `scripts` - folder for scripts. These scripts are referenced in `no-team.controls.yml` and team level `controls.yml`. -- `default.policies.yml` - top-level file with all global policies (aka policies assigned to **all hosts**). -- `default.queries.yml` - top-level file with all global queries (aka queries that run on **all hosts**). -- `no-team.controls.yml` - top-level file with controls (configuration profiles, OS updates, setup experience, and scripts) that apply to **hosts assigned to "No team"**. -- `default.settings.yml` - top-level file with settings. These settings get applied to **hosts assigned to "No team"**. When a new team is created, it gets these settings. -- `teams` - folder for teams in Fleet. These folders contain team-level policies, queries, controls, and settings. - - `` - folder for each team, with team-specific configs. - - `.policies.yml` - policies config for a specific team, including CIS policies. (Team name is duplicated in file name for easy searching.) - - `.queries.yml` - queries config for a specific team. (Team name is duplicated in file name for easy searching.) - - `.controls.yml` - controls config for a specific team, including configuration profiles, OS updates, setup experience, and scripts. - - `.settings.yml` - settings config for a specific team, including agent options, command-line flags, and more. Team settings override global settings. diff --git a/best-practice/default.policies.yml b/best-practice/default.policies.yml deleted file mode 100644 index 9a6ea07..0000000 --- a/best-practice/default.policies.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Policies that run on all hosts ---- -apiVersion: v1 -kind: policy -spec: - name: Google Chrome is up-to-date - platform: darwin,windows - description: Out of date browsers are one of the biggest contributors toward corporate breach scenarios. Ensure your Google Chrome browser has been updated to the latest version. - resolution: https://support.google.com/chrome/answer/95414?hl=en&co=GENIE.Platform%3DDesktop - query: SELECT 1 FROM apps where bundle_identifier="com.google.Chrome" AND bundle_version >= 5615.137; - contributors: dherder \ No newline at end of file diff --git a/best-practice/default.queries.yml b/best-practice/default.queries.yml deleted file mode 100644 index 39422d8..0000000 --- a/best-practice/default.queries.yml +++ /dev/null @@ -1,10 +0,0 @@ -# Queries that run on all hosts ---- -apiVersion: v1 -kind: query -spec: - name: osquery_info - description: A heartbeat counter that reports general performance (CPU, memory) and version. - query: select i.*, p.resident_size, p.user_time, p.system_time, time.minutes as counter from osquery_info i, processes p, time where p.pid = i.pid; - interval: 3600 # 1 hour - observer_can_run: true \ No newline at end of file diff --git a/best-practice/default.settings.yml b/best-practice/default.settings.yml deleted file mode 100644 index 4d524a9..0000000 --- a/best-practice/default.settings.yml +++ /dev/null @@ -1,144 +0,0 @@ ---- -apiVersion: v1 -kind: config -spec: - agent_options: - command_line_flags: {} - config: - decorators: - load: - - SELECT uuid AS host_uuid FROM system_info; - - SELECT hostname AS hostname FROM system_info; - options: - disable_distributed: false - distributed_interval: 5 - distributed_plugin: tls - distributed_tls_max_attempts: 3 - logger_tls_endpoint: /api/v1/osquery/log - pack_delimiter: / - overrides: - platforms: - darwin: - auto_table_construction: - chrome_browser_history: - columns: - - id - - url - - title - - visit_count - - type_count - - last_visit_time - - hidden - - visit_time - - from_visit - - visit_duration - - transition - - source - path: /Users/%/Library/Application Support/Google/Chrome/%/History - query: SELECT urls.id id, urls.url url, urls.title title, urls.visit_count - visit_count, urls.typed_count typed_count, urls.last_visit_time last_visit_time, - urls.hidden hidden, visits.visit_time visit_time, visits.from_visit - from_visit, visits.visit_duration visit_duration, visits.transition - transition, visit_source.source source FROM urls JOIN visits ON urls.id - = visits.url LEFT JOIN visit_source ON visits.id = visit_source.id - tcc_system_entries: - columns: - - service - - client - - allowed - - prompt_count - - last_modified - path: /Library/Application Support/com.apple.TCC/TCC.db - query: select service, client, allowed, prompt_count, last_modified - from access - windows: - auto_table_construction: - chrome_browser_history: - columns: - - id - - url - - title - - visit_count - - type_count - - last_visit_time - - hidden - - visit_time - - from_visit - - visit_duration - - transition - - source - path: C:\Users\%\AppData\Local\Google\Chrome\User Data\%\History - query: SELECT urls.id id, urls.url url, urls.title title, urls.visit_count - visit_count, urls.typed_count typed_count, urls.last_visit_time last_visit_time, - urls.hidden hidden, visits.visit_time visit_time, visits.from_visit - from_visit, visits.visit_duration visit_duration, visits.transition - transition, visit_source.source source FROM urls JOIN visits ON urls.id - = visits.url LEFT JOIN visit_source ON visits.id = visit_source.id - features: - enable_host_users: true - enable_software_inventory: true - fleet_desktop: - transparency_url: https://fleetdm.com/transparency - host_expiry_settings: - host_expiry_enabled: false - host_expiry_window: 7 - integrations: - jira: null - zendesk: null - mdm: - apple_bm_default_team: "\U0001F4BB Workstations" - apple_bm_enabled_and_configured: true - apple_bm_terms_expired: false - enabled_and_configured: true - end_user_authentication: - entity_id: https://fleetdm.example.com - idp_name: Okta - issuer_uri: "" - metadata: "" - metadata_url: https://okta.com/example - macos_migration: - enable: true - mode: voluntary - webhook_url: https://tines.com/example - macos_settings: - custom_settings: null - enable_disk_encryption: true - macos_setup: - bootstrap_package: "" - enable_end_user_authentication: false - macos_setup_assistant: null - macos_updates: - deadline: "2023-06-12" - minimum_version: 13.4.0 - org_info: - contact_url: https://fleetdm.com/company/contact - org_logo_url: "" - org_name: Fleet Device Management - server_settings: - debug_host_ids: - - 1 - - 3 - deferred_save_host: false - enable_analytics: true - live_query_disabled: false - server_url: https://dogfood.fleetdm.com - vulnerability_settings: - databases_path: "" - webhook_settings: - failing_policies_webhook: - destination_url: https://tines.com/example - enable_failing_policies_webhook: true - host_batch_size: 0 - policy_ids: - - 136 - - 178 - host_status_webhook: - days_count: 1 - destination_url: "" - enable_host_status_webhook: false - host_percentage: 25 - interval: 1m0s - vulnerabilities_webhook: - destination_url: https://tines.com/example - enable_vulnerabilities_webhook: false - host_batch_size: 0 \ No newline at end of file diff --git a/best-practice/no-team.controls.yml b/best-practice/no-team.controls.yml deleted file mode 100644 index b027873..0000000 --- a/best-practice/no-team.controls.yml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: v1 -kind: config -spec: - mdm: - macos_settings: - custom_settings: - - ./mdm-profiles/os-updates.json - - ./mdm-profiles/password-polic.mobile.config - scripts: - - ./scripts/set-timezone.sh - - ./scripts/remove-zoom-artifacts.sh - - ./scripts/uninstall-zoom.sh \ No newline at end of file diff --git a/default.yml b/default.yml new file mode 100644 index 0000000..5b1e5ea --- /dev/null +++ b/default.yml @@ -0,0 +1,54 @@ +# For Fleet Free, this file updates queries, policies, controls, and agent options for all hosts. + +# For Fleet Premium, the default.yml file updates queries and policies that run on all hosts ("All teams"). Controls and agent options are updated for hosts on "No team." + +controls: # Controls added to "No team" + macos_settings: + custom_settings: + - path: ../lib/macos-os-updates.ddm.json + - path: ../lib/macos-password.mobileconfig + windows_settings: + custom_settings: + - path: ../lib/windows-screenlock.xml + scripts: + - path: ../lib/collect-fleetd-logs.sh +queries: +- path: ./lib/collect-fleetd-update-channel.queries.yml +policies: +agent_options: ./lib/agent-options.yml +org_settings: + server_settings: + debug_host_ids: + - 1 + - 3 + enable_analytics: true + live_query_disabled: false + query_reports_disabled: false + scripts_disabled: false + server_url: https://dogfood.fleetdm.com + org_info: + contact_url: https://fleetdm.com/company/contact + org_logo_url: "" + org_logo_url_light_background: "" + org_name: Fleet Device Management + smtp_settings: + sso_settings: + enable_jit_provisioning: true + enable_jit_role_sync: false + enable_sso: true + enable_sso_idp_login: false + idp_name: Google Workspace + entity_id: dogfood.fleetdm.com + metadata: $FLEET_SSO_METADATA + integrations: + mdm: + apple_bm_default_team: Workstations + webhook_settings: + vulnerabilities_webhook: + enable_vulnerabilities_webhook: true + destination_url: https://example.tines.com/webhook + fleet_desktop: # Applies to Fleet Premium only + transparency_url: https://fleetdm.com/transparency + host_expiry_settings: # Applies to all teams + host_expiry_enabled: false + features: # Features added to all teams \ No newline at end of file diff --git a/example-workflow.yml b/example-workflow.yml deleted file mode 100644 index 0aeb389..0000000 --- a/example-workflow.yml +++ /dev/null @@ -1,44 +0,0 @@ -# This workflow applies the latest configuration profiles (macOS settings) and macOS updates minimum version and deadline to the provided team. -name: Apply latest configuration profiles (example) -on: - push: - branches: - - main - paths: - - "path/to/**.mobileconfig" - workflow_dispatch: # Manual - -# This allows a subsequently queued workflow run to interrupt previous runs -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id}} - cancel-in-progress: true - -defaults: - run: - # fail-fast using bash -eo pipefail. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference - shell: bash - -permissions: - contents: read - -env: - FLEET_API_TOKEN: ${{ secrets.DOGFOOD_API_TOKEN }} - FLEET_URL: ${{ secrets.DOGFOOD_URL }} - TOKEN_USED_BY_PROFILE: ${{ secrets.TOKEN_USED_BY_PROFILE }} - -jobs: - apply-profiles: - timeout-minutes: 5 - runs-on: ubuntu-latest - steps: - - name: Apply configuration profiles and updates - uses: fleetdm/fleet-mdm-gitops@026ee84a69cb89c869fedbe27c969bf89def418b - with: - FLEET_API_TOKEN: $FLEET_API_TOKEN - FLEET_URL: $FLEET_URL - FLEET_TEAM_NAME: Workstations - MDM_CONFIG_REPO: fleetdm/fleet - MDM_CONFIG_DIRECTORY: mdm_profiles - MAC_OS_MIN_VERSION: 13.4.0 - MAC_OS_VERSION_DEADLINE: 2023-06-15 - MAC_OS_ENABLE_DISK_ENCRYPTION: true diff --git a/lib/agent-options.yml b/lib/agent-options.yml new file mode 100644 index 0000000..9137faa --- /dev/null +++ b/lib/agent-options.yml @@ -0,0 +1,13 @@ +command_line_flags: {} +config: + decorators: + load: + - SELECT uuid AS host_uuid FROM system_info; + - SELECT hostname AS hostname FROM system_info; + options: + disable_distributed: false + distributed_interval: 5 + distributed_plugin: tls + distributed_tls_max_attempts: 3 + logger_tls_endpoint: /api/v1/osquery/log + pack_delimiter: / \ No newline at end of file diff --git a/lib/collect-failed-login-attempts.queryies.yml b/lib/collect-failed-login-attempts.queryies.yml new file mode 100644 index 0000000..e139464 --- /dev/null +++ b/lib/collect-failed-login-attempts.queryies.yml @@ -0,0 +1,6 @@ +- name: Collect failed login attempts + description: Lists the users at least one failed login attempt and timestamp of failed login. Number of failed login attempts reset to zero after a user successfully logs in. + query: SELECT users.username, account_policy_data.failed_login_count, account_policy_data.failed_login_timestamp FROM users INNER JOIN account_policy_data using (uid) WHERE account_policy_data.failed_login_count > 0; + interval: 300 # 5 minutes + observer_can_run: false + automations_enabled: false \ No newline at end of file diff --git a/lib/collect-fleetd-logs.sh b/lib/collect-fleetd-logs.sh new file mode 100644 index 0000000..887af2a --- /dev/null +++ b/lib/collect-fleetd-logs.sh @@ -0,0 +1,7 @@ +cp /var/log/orbit/orbit.stderr.log ~/Library/Logs/Fleet/fleet-desktop.log /Users/Shared + +echo "Successfully copied fleetd logs to the /Users/Shared folder." + +echo "To retrieve logs, ask the end user to open Finder and in the menu bar select Go > Go to Folder." + +echo "Then, ask the end user to type in /Users/Shared, press Return, and locate orbit.stderr.log (Orbit logs) and fleet-desktop.log (Fleet Desktop logs) files." \ No newline at end of file diff --git a/lib/collect-fleetd-update-channels.queries.yml b/lib/collect-fleetd-update-channels.queries.yml new file mode 100644 index 0000000..90f1e26 --- /dev/null +++ b/lib/collect-fleetd-update-channels.queries.yml @@ -0,0 +1,6 @@ +- name: Collect fleetd update channels + description: "Collects the update channels for all fleetd components: osquery, Orbit, and Fleet Desktop. To see which version number each channel is on, ask in #help-engineering." + query: SELECT desktop_channel, orbit_channel, osqueryd_channel FROM orbit_info; + interval: 300 # 5 minutes + observer_can_run: true + automations_enabled: false diff --git a/lib/collect-usb-devices.queries.yml b/lib/collect-usb-devices.queries.yml new file mode 100644 index 0000000..795c5b8 --- /dev/null +++ b/lib/collect-usb-devices.queries.yml @@ -0,0 +1,6 @@ +- name: Collect USB devices + description: Collects the USB devices that are currently connected to macOS and Linux hosts. + query: SELECT model, vendor FROM usb_devices; + interval: 300 # 5 minutes + observer_can_run: true + automations_enabled: false \ No newline at end of file diff --git a/lib/device-health.policies.yml b/lib/device-health.policies.yml new file mode 100644 index 0000000..ef99d68 --- /dev/null +++ b/lib/device-health.policies.yml @@ -0,0 +1,250 @@ +- name: macOS - CIS - Ensure FileVault is enabled (MDM required) + platform: darwin + description: Checks that FileVault is enabled. FileVault secures a system's data by automatically encrypting its boot volume and requiring a password or recovery key to access it. This policy checks that filevault is enabled on the device and that the user is not allowed to disable it. + resolution: | + Automated method: + Ask your system administrator to deploy an MDM profile that enables FileVault and disables turning it off. + Graphical method: + Perform the following steps to ensure FileVault Is Enabled: + 1. Open System Settings + 2. Select Privacy & Privacy + 3. Verify that FileVault states FileVault is turned on for the disk "" + 4. Select Privacy & Security + 5. Select Profile + 6. Verify that an installed profile has FileVault Can't Disable set to True + query: | + SELECT 1 WHERE + EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.MCX' AND + name='dontAllowFDEDisable' AND + (value = 1 OR value = 'true') AND + username = '' + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.MCX' AND + name='dontAllowFDEDisable' AND + (value != 1 AND value != 'true') + ) + AND EXISTS ( + SELECT 1 FROM disk_encryption WHERE + user_uuid IS NOT "" AND + filevault_status = 'on' + ); +- name: macOS - CIS - Ensure Firewall logging is enabled and configured (MDM required) + platform: darwin + description: | + The socketfilter Firewall is what is used when the Firewall is turned on in the Security & Privacy Preference Pane. In order to appropriately monitor what access is allowed and denied, logging must be enabled. The logging level must be set to "detailed" to be useful in monitoring connection attempts that the firewall detects. Throttled login is not sufficient for examine Firewall connection attempts. + resolution: | + Profile Method: + Create or edit a configuration profile with the following information: + 1. The Payload Type string is com.apple.security.firewall + 2. The key to include is EnableFirewall + 3. The key must be set to + 4. The key to also include is EnableLogging + 5. The key must be set to + 6. The key to also include is LoggingOption + 7. The key must be set to detail + query: | + SELECT 1 WHERE + ( + EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.security.firewall' AND + name='EnableLogging' AND + (value = 1 OR value = 'true') AND + username = '' + ) + AND EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.security.firewall' AND + name='LoggingOption' AND + value = "detail" AND + username = '' + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.security.firewall' AND + name='EnableLogging' AND + (value != 1 AND value != 'true') + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.security.firewall' AND + name='LoggingOption' AND + value != "detail" + ) + ) + OR + ( + EXISTS ( + SELECT 1 FROM plist WHERE + path='/Library/Preferences/com.apple.alf.plist' AND + key='loggingenabled' AND + value = 1 + ) + AND EXISTS ( + SELECT 1 FROM plist WHERE + path='/Library/Preferences/com.apple.alf.plist' AND + key='loggingoption' AND + value = 2 + ) + ); +- name: macOS - CIS - Ensure NFS server is disabled + platform: darwin + description: | + macOS can act as an NFS fileserver. NFS sharing could be enabled to allow someone on another computer to mount + shares and gain access to information from the user's computer. + resolution: | + Automated method: + Ask your system administrator to deploy the following script which will disable the NFS service + and its directory listing: + /usr/bin/sudo /bin/launchctl disable system/com.apple.nfsd + /usr/bin/sudo /bin/rm /etc/exports + query: | + SELECT 1 WHERE + NOT EXISTS(SELECT 1 FROM processes WHERE path = '/sbin/nfsd') + AND + NOT EXISTS(SELECT 1 FROM file WHERE path = '/etc/exports'); +- name: macOS - CIS - Ensure Remote Application Scripting is disabled + platform: darwin + description: | + Apple Application Scripting is a technology that allows one program to communicate with other programs. + Remote Apple Application Scripting allows a program on one computer to communicate with a program on a + different computer. Disabling Remote Application Scripting mitigates the risk of an unauthorized + program gaining access to the system. + resolution: | + Graphical Method: + 1. Open System Settings + 2. Select General + 3. Select Sharing + 4. Set Remote Application Scripting to disabled + query: | + SELECT 1 WHERE NOT EXISTS ( + SELECT * FROM plist WHERE + path = '/var/db/com.apple.xpc.launchd/disabled.plist' AND + key = 'com.apple.AEServer' AND + value = 0 + ); +- name: macOS - CIS - Ensure Remote Login is disabled + platform: darwin + description: | + Remote Login allows an interactive terminal session to a computer. + The SSH server built into macOS should not be enabled on a standard user computer, + particularly one that changes locations and IP addresses. + A standard user that runs local applications, including email, web browser, + and productivity tools, should not use the same device as a server + + resolution: | + Graphical Method: + 1. Open System Settings + 2. Select General + 3. Select Sharing + 4. Set Remote Login to disabled + query: | + SELECT 1 WHERE NOT EXISTS ( + SELECT * FROM plist WHERE + path = '/var/db/com.apple.xpc.launchd/disabled.plist' AND + key = 'com.openssh.sshd' AND + value = '0' + ); +- name: macOS - CIS - Ensure Remote Management is disabled + platform: darwin + description: | + Remote Management is the client portion of Apple Remote Desktop (ARD). + Remote Management can be used by remote administrators to view the current screen, + install software, report on, and generally manage client Macs. + Remote Management should only be enabled on trusted networks with strong + user controls present in a Directory system. + Mobile devices without strict controls are vulnerable to exploit and monitoring. + resolution: | + Graphical Method: + 1. Open System Settings + 2. Select General + 3. Select Sharing + 4. Set Remote Management to disabled + query: | + SELECT 1 WHERE NOT EXISTS ( + SELECT * FROM processes WHERE + path = '/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent' + ); +- name: macOS - CIS - Ensure an Inactivity Interval of 20 Minutes Or Less for the Screen Saver Is Enabled (MDM Required) + platform: darwin + description: A locking screen saver is one of the standard security controls to limit access to a computer and the current user's session when the computer is temporarily unused or unattended. In macOS, the screen saver starts after a value is selected in the drop- down menu. 20 minutes or less is an acceptable value. Any value can be selected through the command line or script, but a number that is not reflected in the GUI can be problematic. 20 minutes is the default for new accounts. + resolution: | + Automated method: + Ask your system administrator to deploy an MDM profile that ensure an Inactivity Interval of 20 Minutes Or Less for the Screen Saver to be Enabled. + Graphical method: + Perform the following steps to ensure an Inactivity Interval of 20 Minutes Or Less for the Screen Saver Is Enabled: + 1. Open System Settings + 2. Select Lock Screen + 3. Verify that Start Screen Saver when inactive is set for 20 minutes or less (≤1200 seconds) + query: | + SELECT 1 WHERE + EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='idleTime' AND + CAST(value AS INT) <= 1200 AND + username = '' + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='idleTime' AND + CAST(value AS INT) > 1200 + ); +- name: macOS - CIS - Ensure Password is Required to Wake the Computer From Sleep or Screen Saver is enabled (MDM Required) + platform: darwin + description: Checks that Password is Required to Wake the Computer From Sleep or Screen Saver is enabled. + resolution: | + Automated method: + Ask your system administrator to deploy an MDM profile that Ensure a Password is Required to Wake the Computer From Sleep or Screen Saver Is Enabled. + Graphical method: + Perform the following steps to ensure a Password is Required to Wake the Computer From Sleep or Screen Saver Is Enabled: + 1. Open System Settings + 2. Select Lock Screen + 3. Verify that Require password after screensaver begins or display is turned + off is set with After 0 seconds or After 5 seconds + query: | + SELECT 1 WHERE + EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='askForPassword' AND + (value = 1 OR value = 'true') AND + username = '' + ) + AND EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='askForPasswordDelay' AND + value <= 60 AND + username = '' + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='askForPassword' AND + (value != 1 AND value != 'true') + ) + AND NOT EXISTS ( + SELECT 1 FROM managed_policies WHERE + domain='com.apple.screensaver' AND + name='askForPasswordDelay' AND + value > 60 + ); +- name: macOS - CIS - Ensure System Integrity Protection Status (SIP) is enabled + platform: darwin + description: | + System Integrity Protection is a security feature introduced in OS X 10.11 El Capitan. System Integrity Protection restricts access to System domain locations and restricts runtime attachment to system processes. Any attempt to inspect or attach to a system process will fail. Kernel Extensions are now restricted to /Library/Extensions and are required to be signed with a Developer ID. + resolution: | + Terminal Method: + Perform the following steps to enable System Integrity Protection: + 1. Reboot into the Recovery Partition (reboot and hold down Command (⌘) + R) + 2. Select Utilities + 3. Select Terminal + 4. Run the following command: + /usr/bin/sudo /usr/bin/csrutil enable + query: SELECT 1 FROM sip_config WHERE config_flag="sip" and enabled=1; \ No newline at end of file diff --git a/lib/macos-os-updates.ddm.json b/lib/macos-os-updates.ddm.json new file mode 100644 index 0000000..c7ae252 --- /dev/null +++ b/lib/macos-os-updates.ddm.json @@ -0,0 +1,10 @@ +{ + "Type": "com.apple.configuration.softwareupdate.enforcement.specific", + "Identifier": "B6965621-36DF-46F6-839D-0F6591C9CA57", + "SeverToken": "20DD77EF-A359-4D63-87AA-30AFC916B261", + "Payload": { + "TargetOSVersion": "14.1", + "TargetBuildVersion": "20A242", + "TargetLocalDateTime": "2023-09-01T10:00:00" + } +} \ No newline at end of file diff --git a/lib/macos-password.mobileconfig b/lib/macos-password.mobileconfig new file mode 100644 index 0000000..2fe2f71 --- /dev/null +++ b/lib/macos-password.mobileconfig @@ -0,0 +1,55 @@ + + + + + PayloadContent + + + PayloadDescription + Configures Passcode settings + PayloadDisplayName + Passcode + PayloadIdentifier + com.github.erikberglund.ProfileCreator.F7CF282E-D91B-44E9-922F-A719634F9C8E.com.apple.mobiledevice.passwordpolicy.231DFC90-D5A7-41B8-9246-564056048AC5 + PayloadOrganization + + PayloadType + com.apple.mobiledevice.passwordpolicy + PayloadUUID + 231DFC90-D5A7-41B8-9246-564056048AC5 + PayloadVersion + 1 + allowSimple + + forcePIN + + maxFailedAttempts + 11 + maxGracePeriod + 1 + maxInactivity + 15 + minLength + 10 + requireAlphanumeric + + + + PayloadDescription + Configures our Macs to require passwords that are 10 character long + PayloadDisplayName + Password policy - require 10 characters + PayloadIdentifier + com.github.erikberglund.ProfileCreator.F7CF282E-D91B-44E9-922F-A719634F9C8E + PayloadOrganization + FleetDM + PayloadScope + System + PayloadType + Configuration + PayloadUUID + F7CF282E-D91B-44E9-922F-A719634F9C8E + PayloadVersion + 1 + + \ No newline at end of file diff --git a/best-practice/scripts/remove-zoom-artifacts.sh b/lib/remove-zoom-artifacts.script.sh similarity index 100% rename from best-practice/scripts/remove-zoom-artifacts.sh rename to lib/remove-zoom-artifacts.script.sh diff --git a/best-practice/scripts/set-timezone.sh b/lib/set-timezone.script.sh similarity index 100% rename from best-practice/scripts/set-timezone.sh rename to lib/set-timezone.script.sh diff --git a/best-practice/scripts/uninstall-zoom.sh b/lib/uninstall-zoom.script.sh similarity index 100% rename from best-practice/scripts/uninstall-zoom.sh rename to lib/uninstall-zoom.script.sh diff --git a/lib/windows-screenlock.xml b/lib/windows-screenlock.xml new file mode 100644 index 0000000..3d7d52d --- /dev/null +++ b/lib/windows-screenlock.xml @@ -0,0 +1,48 @@ + + + + + int + + + ./Device/Vendor/MSFT/Policy/Config/DeviceLock/DevicePasswordEnabled + + 0 + + + + + + + int + + + ./Device/Vendor/MSFT/Policy/Config/DeviceLock/MaxInactivityTimeDeviceLock + + 15 + + + + + + + int + + + ./Device/Vendor/MSFT/Policy/Config/DeviceLock/MinDevicePasswordLength + + 10 + + + + + + + int + + + ./Device/Vendor/MSFT/Policy/Config/DeviceLock/MinDevicePasswordComplexCharacters + + 2 + + diff --git a/teams/workstations-canary.yml b/teams/workstations-canary.yml new file mode 100644 index 0000000..a0991f0 --- /dev/null +++ b/teams/workstations-canary.yml @@ -0,0 +1,45 @@ +# Only available in Fleet Premium. + +#This file updates controls, queries, policies, and agent options for assigned to the "Workstations (canary)" team. + +# To create and update another team, create another file in the teams/ directory and copy and paste the contents from this file. + +name: Workstations (canary) +controls: + enable_disk_encryption: true + macos_updates: + deadline: "2023-08-11" + minimum_version: "13.5" + windows_updates: + deadline: "5" + grace_period: "2" + macos_settings: + custom_settings: + - path: ../lib/macos-os-updates.ddm.json + - path: ../lib/macos-password.mobileconfig + windows_settings: + custom_settings: + - path: ../lib/windows-screenlock.xml + macos_setup: + bootstrap_package: + enable_end_user_authentication: + macos_setup_assistant: + scripts: + - path: ../lib/remove-zoom-artifacts.script.sh + - path: ../lib/reset-timezone.sh +queries: +- path: ../lib/collect-usb-devices.queries.yml +- path: ../lib/collect-failed-login-attempts.queries.yml +- name: Collect fleetd update channels + description: "Collects the update channels for all fleetd components: osquery, Orbit, and Fleet Desktop. To see which version number each channel is on, ask in #help-engineering." + query: SELECT desktop_channel, orbit_channel, osqueryd_channel FROM orbit_info; + interval: 300 + observer_can_run: true + automations_enabled: false +policies: +- path: ../lib/device-health.policies.yml +agent_options: ./lib/agent-options.yml +team_settings: + webhook_settings: + secrets: + - secret: $FLEET_WORKSTATIONS_CANARY_ENROLL_SECRET \ No newline at end of file diff --git a/teams/workstations.yml b/teams/workstations.yml new file mode 100644 index 0000000..0f0e916 --- /dev/null +++ b/teams/workstations.yml @@ -0,0 +1,44 @@ +# Only available in Fleet Premium. + +#This file updates controls, queries, policies, and agent options for assigned to the "Workstations" team. + +# To create and update another team, create another file in the teams/ directory and copy and paste the contents from this file. + +name: Workstations +controls: + enable_disk_encryption: true + macos_updates: + deadline: "2023-08-11" + minimum_version: "13.5" + windows_updates: + deadline: "5" + grace_period: "2" + macos_settings: + custom_settings: + - path: ../lib/macos-os-updates.ddm.json + - path: ../lib/macos-password.mobileconfig + windows_settings: + custom_settings: + - path: ../lib/windows-screenlock.xml + macos_setup: + bootstrap_package: + enable_end_user_authentication: + macos_setup_assistant: + scripts: + - path: ../lib/remove-zoom-artifacts.script.sh + - path: ../lib/reset-timezone.sh +queries: +- path: ../lib/collect-usb-devices.queries.yml +- path: ../lib/collect-failed-login-attempts.queries.yml +policies: +- path: ../lib/device-health.policies.yml +agent_options: ./lib/agent-options.yml +team_settings: + webhook_settings: + failing_policies_webhook: + enable_failing_policies_webhook: true + destination_url: https://example.tines.com/webhook + policy_ids: [1, 2, 3, 4, 5,6 ,7, 8, 9] + secrets: + - secret: $FLEET_WORKSTATIONS_ENROLL_SECRET + \ No newline at end of file