mdm-device-management

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Mobile Device Management (MDM) for Startups & Small Teams

面向初创企业与小型团队的移动设备管理(MDM)指南

A practical guide to enrolling, securing, and managing company devices across macOS, Windows, iOS, and Android — from zero-touch onboarding to remote wipe.

一份实用指南,涵盖macOS、Windows、iOS和Android设备的注册、安全防护与管理——从零接触入职到远程擦除全流程。

1. When to Use MDM

1. 何时使用MDM

MDM becomes essential when any of the following apply:
  • Team size crosses ~10 people — manual laptop setup no longer scales.
  • Compliance requirements — SOC 2, HIPAA, ISO 27001, or customer security questionnaires demand proof that endpoints are encrypted and patched.
  • Remote / hybrid workforce — you cannot walk over to someone's desk to fix a configuration or verify disk encryption.
  • Contractor or BYOD devices — you need a way to separate corporate data from personal data and revoke access on offboarding.
  • Insurance or investor due diligence — cyber-insurance carriers and VCs increasingly ask for evidence of endpoint management.
If you are still under 10 people and everyone is in-office, a simple checklist plus a configuration management tool (Ansible) may suffice — but plan for MDM early so enrollment is painless when you scale.

当出现以下任一情况时,MDM就变得必不可少:
  • 团队规模达到约10人——手动设置笔记本电脑的方式不再具备可扩展性。
  • 合规要求——SOC 2、HIPAA、ISO 27001等合规标准,或客户的安全问卷,要求提供终端设备已加密并完成补丁更新的证明。
  • 远程/混合办公模式——你无法走到员工工位去修复配置或验证磁盘加密状态。
  • 承包商或自带设备(BYOD)场景——你需要区分企业数据与个人数据,并在员工离职时收回访问权限。
  • 保险或投资者尽职调查——网络保险公司和风险投资机构越来越多地要求提供终端管理的证据。
如果你的团队规模仍不足10人且全员线下办公,简单的检查清单加配置管理工具(如Ansible)可能就足够了——但要尽早规划MDM,以便在团队扩张时能顺利完成设备注册。

2. MDM Platform Comparison

2. MDM平台对比

PlatformBest ForPricing ModelOpen SourceKey Strength
Jamf PromacOS / iOS fleetsPer-device/yrNoDeepest Apple integration, DEP/ADE native
Microsoft IntuneWindows + M365 shopsBundled w/ M365 E3/E5NoSeamless Azure AD + Autopilot
KandjimacOS-first startupsPer-device/yrNoPre-built compliance templates, fast setup
MosyleEducation & SMB ApplePer-device/yrNoApple School/Business Manager integration
FleetCross-platform, eng-ledFree (OSS) / paid cloudYesosquery-powered, GitOps-friendly, API-first
SimpleMDMSmall Apple-only teamsPer-device/moNoSimple UI, quick onboarding
平台适用场景定价模式是否开源核心优势
Jamf PromacOS/iOS设备集群按设备/年收费最深度的Apple集成,原生支持DEP/ADE
Microsoft IntuneWindows + M365环境包含在M365 E3/E5套餐中与Azure AD和Autopilot无缝集成
Kandji以macOS为主的初创企业按设备/年收费预构建合规模板,快速部署
Mosyle教育行业与小型Apple设备集群按设备/年收费集成Apple School/Business Manager
Fleet跨平台、技术团队主导的场景免费(开源版)/付费云服务基于osquery,支持GitOps,API优先
SimpleMDM小型纯Apple设备团队按设备/月收费UI简洁,快速上手

Decision heuristic

决策准则

text
if (team < 50 AND engineering-led AND multi-OS):
    consider Fleet (open-source, osquery-native)
elif (team is macOS-dominant AND compliance-heavy):
    consider Kandji or Jamf
elif (team is Windows-dominant AND already on M365):
    consider Intune (likely already licensed)
else:
    evaluate Fleet or Kandji based on OS mix

text
if (team < 50 AND engineering-led AND multi-OS):
    consider Fleet (open-source, osquery-native)
elif (team is macOS-dominant AND compliance-heavy):
    consider Kandji or Jamf
elif (team is Windows-dominant AND already on M365):
    consider Intune (likely already licensed)
else:
    evaluate Fleet or Kandji based on OS mix

3. Fleet (Open Source MDM) — Self-Hosted Deployment

3. Fleet(开源MDM)——自托管部署

Fleet is the leading open-source MDM. It uses osquery under the hood and supports macOS, Windows, Linux, iOS, and Android.
Fleet是领先的开源MDM工具,底层基于osquery,支持macOS、Windows、Linux、iOS和Android。

3.1 Docker Compose deployment

3.1 Docker Compose部署

yaml
undefined
yaml
undefined

docker-compose.yml

docker-compose.yml

version: "3.8"
services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: "${FLEET_MYSQL_ROOT_PASSWORD}" MYSQL_DATABASE: fleet MYSQL_USER: fleet MYSQL_PASSWORD: "${FLEET_MYSQL_PASSWORD}" volumes: - mysql-data:/var/lib/mysql ports: - "3306:3306" healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s retries: 5
redis: image: redis:7-alpine ports: - "6379:6379"
fleet: image: fleetdm/fleet:v4.47.0 depends_on: mysql: condition: service_healthy redis: condition: service_started environment: FLEET_MYSQL_ADDRESS: mysql:3306 FLEET_MYSQL_DATABASE: fleet FLEET_MYSQL_USERNAME: fleet FLEET_MYSQL_PASSWORD: "${FLEET_MYSQL_PASSWORD}" FLEET_REDIS_ADDRESS: redis:6379 FLEET_SERVER_TLS: "true" FLEET_SERVER_TLS_COMPATIBILITY: modern FLEET_SERVER_CERT: /tls/fleet.crt FLEET_SERVER_KEY: /tls/fleet.key FLEET_LOGGING_JSON: "true" volumes: - ./tls:/tls:ro ports: - "8080:8080"
volumes: mysql-data:
undefined
version: "3.8"
services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: "${FLEET_MYSQL_ROOT_PASSWORD}" MYSQL_DATABASE: fleet MYSQL_USER: fleet MYSQL_PASSWORD: "${FLEET_MYSQL_PASSWORD}" volumes: - mysql-data:/var/lib/mysql ports: - "3306:3306" healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s retries: 5
redis: image: redis:7-alpine ports: - "6379:6379"
fleet: image: fleetdm/fleet:v4.47.0 depends_on: mysql: condition: service_healthy redis: condition: service_started environment: FLEET_MYSQL_ADDRESS: mysql:3306 FLEET_MYSQL_DATABASE: fleet FLEET_MYSQL_USERNAME: fleet FLEET_MYSQL_PASSWORD: "${FLEET_MYSQL_PASSWORD}" FLEET_REDIS_ADDRESS: redis:6379 FLEET_SERVER_TLS: "true" FLEET_SERVER_TLS_COMPATIBILITY: modern FLEET_SERVER_CERT: /tls/fleet.crt FLEET_SERVER_KEY: /tls/fleet.key FLEET_LOGGING_JSON: "true" volumes: - ./tls:/tls:ro ports: - "8080:8080"
volumes: mysql-data:
undefined

3.2 Initial setup

3.2 初始设置

bash
undefined
bash
undefined

Generate TLS certs (use real certs in production)

生成TLS证书(生产环境请使用正式证书)

mkdir -p tls openssl req -x509 -newkey rsa:4096 -sha256 -days 365
-nodes -keyout tls/fleet.key -out tls/fleet.crt
-subj "/CN=fleet.yourcompany.com"
mkdir -p tls openssl req -x509 -newkey rsa:4096 -sha256 -days 365
-nodes -keyout tls/fleet.key -out tls/fleet.crt
-subj "/CN=fleet.yourcompany.com"

Start services

启动服务

docker compose up -d
docker compose up -d

Create admin account

创建管理员账户

docker compose exec fleet fleet prepare db docker compose exec fleet fleet setup
--email admin@yourcompany.com
--name "IT Admin"
--password "${FLEET_ADMIN_PASSWORD}"
--org-name "YourCompany"
undefined
docker compose exec fleet fleet prepare db docker compose exec fleet fleet setup
--email admin@yourcompany.com
--name "IT Admin"
--password "${FLEET_ADMIN_PASSWORD}"
--org-name "YourCompany"
undefined

3.3 Enroll a macOS host with fleetctl

3.3 使用fleetctl注册macOS主机

bash
undefined
bash
undefined

Install fleetctl

安装fleetctl

brew install fleetdm/tap/fleetctl
brew install fleetdm/tap/fleetctl

Authenticate

认证

fleetctl config set --address https://fleet.yourcompany.com:8080 fleetctl login --email admin@yourcompany.com
fleetctl config set --address https://fleet.yourcompany.com:8080 fleetctl login --email admin@yourcompany.com

Generate an installer package for macOS

生成macOS安装包

fleetctl package --type pkg
--fleet-url https://fleet.yourcompany.com:8080
--enroll-secret "$(fleetctl get enroll-secret)"
--fleet-certificate tls/fleet.crt
fleetctl package --type pkg
--fleet-url https://fleet.yourcompany.com:8080
--enroll-secret "$(fleetctl get enroll-secret)"
--fleet-certificate tls/fleet.crt

The .pkg file can be distributed via Apple Business Manager or manually

.pkg文件可通过Apple Business Manager分发或手动安装

undefined
undefined

3.4 Enroll a Windows host

3.4 注册Windows主机

powershell
undefined
powershell
undefined

Download the Fleet osquery MSI installer

下载Fleet osquery MSI安装包

fleetctl package --type msi
  --fleet-url https://fleet.yourcompany.com:8080
--enroll-secret "$(fleetctl get enroll-secret)" ` --fleet-certificate tls/fleet.crt
fleetctl package --type msi
  --fleet-url https://fleet.yourcompany.com:8080
--enroll-secret "$(fleetctl get enroll-secret)" ` --fleet-certificate tls/fleet.crt

Install silently

静默安装

msiexec /i fleet-osquery.msi /quiet /norestart
undefined
msiexec /i fleet-osquery.msi /quiet /norestart
undefined

3.5 osquery policy examples in Fleet

3.5 Fleet中的osquery策略示例

yaml
undefined
yaml
undefined

fleet-policies.yml — apply with: fleetctl apply -f fleet-policies.yml

fleet-policies.yml — 使用以下命令应用:fleetctl apply -f fleet-policies.yml

apiVersion: v1 kind: policy spec: name: FileVault enabled (macOS) query: > SELECT 1 FROM disk_encryption WHERE user_uuid IS NOT '' AND encrypted = 1; description: Ensures FileVault disk encryption is enabled. resolution: "Enable FileVault: System Settings > Privacy & Security > FileVault." platform: darwin

apiVersion: v1 kind: policy spec: name: BitLocker enabled (Windows) query: > SELECT 1 FROM bitlocker_info WHERE protection_status = 1; description: Ensures BitLocker drive encryption is active. resolution: "Enable BitLocker via Settings > Privacy & Security > Device Encryption." platform: windows

apiVersion: v1 kind: policy spec: name: Firewall enabled (macOS) query: > SELECT 1 FROM alf WHERE global_state >= 1; description: macOS Application Layer Firewall must be on. resolution: "Enable firewall: System Settings > Network > Firewall." platform: darwin

apiVersion: v1 kind: policy spec: name: OS up to date (macOS) query: > SELECT 1 FROM os_version WHERE platform = 'darwin' AND major >= 14; description: Requires macOS 14 (Sonoma) or later. resolution: "Update macOS via System Settings > General > Software Update." platform: darwin

---
apiVersion: v1 kind: policy spec: name: FileVault enabled (macOS) query: > SELECT 1 FROM disk_encryption WHERE user_uuid IS NOT '' AND encrypted = 1; description: Ensures FileVault disk encryption is enabled. resolution: "Enable FileVault: System Settings > Privacy & Security > FileVault." platform: darwin

apiVersion: v1 kind: policy spec: name: BitLocker enabled (Windows) query: > SELECT 1 FROM bitlocker_info WHERE protection_status = 1; description: Ensures BitLocker drive encryption is active. resolution: "Enable BitLocker via Settings > Privacy & Security > Device Encryption." platform: windows

apiVersion: v1 kind: policy spec: name: Firewall enabled (macOS) query: > SELECT 1 FROM alf WHERE global_state >= 1; description: macOS Application Layer Firewall must be on. resolution: "Enable firewall: System Settings > Network > Firewall." platform: darwin

apiVersion: v1 kind: policy spec: name: OS up to date (macOS) query: > SELECT 1 FROM os_version WHERE platform = 'darwin' AND major >= 14; description: Requires macOS 14 (Sonoma) or later. resolution: "Update macOS via System Settings > General > Software Update." platform: darwin

---

4. macOS Enrollment

4. macOS设备注册

4.1 Apple Business Manager (ABM) / Automated Device Enrollment

4.1 Apple Business Manager (ABM) / 自动化设备注册

bash
undefined
bash
undefined

In ABM (business.apple.com):

在ABM(business.apple.com)中:

1. Settings > MDM Servers > Add MDM Server

1. 设置 > MDM服务器 > 添加MDM服务器

2. Upload the public key from your MDM (Fleet, Jamf, Kandji)

2. 上传MDM工具(Fleet、Jamf、Kandji)的公钥

3. Download the ABM token and upload it to your MDM

3. 下载ABM令牌并上传至你的MDM工具

4. Assign devices to the MDM server by serial number

4. 通过序列号将设备分配给MDM服务器

Verify DEP assignment with fleetctl (Fleet)

使用fleetctl验证DEP分配状态(Fleet)

fleetctl get mdm-apple
undefined
fleetctl get mdm-apple
undefined

4.2 Manual MDM profile enrollment (non-DEP devices)

4.2 手动MDM配置文件注册(非DEP设备)

bash
undefined
bash
undefined

Generate enrollment profile URL (Fleet example)

生成注册配置文件URL(Fleet示例)

fleetctl get enrollment-profile > enrollment.mobileconfig
fleetctl get enrollment-profile > enrollment.mobileconfig

Distribute to user — they open the .mobileconfig file

分发给用户——用户打开.mobileconfig文件

Then approve in System Settings > Profiles

然后在系统设置 > 配置文件中批准

undefined
undefined

4.3 Enforce FileVault via MDM configuration profile

4.3 通过MDM配置文件强制启用FileVault

xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.apple.MCX.FileVault2</string>
            <key>PayloadIdentifier</key>
            <string>com.yourcompany.filevault</string>
            <key>PayloadUUID</key>
            <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>Enable</key>
            <string>On</string>
            <key>Defer</key>
            <true/>
            <key>DeferForceAtUserLoginMaxBypassAttempts</key>
            <integer>0</integer>
            <key>ShowRecoveryKey</key>
            <false/>
            <key>UseRecoveryKey</key>
            <true/>
        </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>FileVault Enforcement</string>
    <key>PayloadIdentifier</key>
    <string>com.yourcompany.filevault.profile</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>F1E2D3C4-B5A6-7890-FEDC-BA0987654321</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.apple.MCX.FileVault2</string>
            <key>PayloadIdentifier</key>
            <string>com.yourcompany.filevault</string>
            <key>PayloadUUID</key>
            <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
            <key>PayloadVersion</key>
            <integer>1</integer>
            <key>Enable</key>
            <string>On</string>
            <key>Defer</key>
            <true/>
            <key>DeferForceAtUserLoginMaxBypassAttempts</key>
            <integer>0</integer>
            <key>ShowRecoveryKey</key>
            <false/>
            <key>UseRecoveryKey</key>
            <true/>
        </dict>
    </array>
    <key>PayloadDisplayName</key>
    <string>FileVault Enforcement</string>
    <key>PayloadIdentifier</key>
    <string>com.yourcompany.filevault.profile</string>
    <key>PayloadType</key>
    <string>Configuration</string>
    <key>PayloadUUID</key>
    <string>F1E2D3C4-B5A6-7890-FEDC-BA0987654321</string>
    <key>PayloadVersion</key>
    <integer>1</integer>
</dict>
</plist>

4.4 macOS firewall enforcement

4.4 macOS防火墙强制启用

bash
undefined
bash
undefined

Enable firewall via MDM command or script

通过MDM命令或脚本启用防火墙

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned enable

---
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned enable

---

5. Windows Enrollment

5. Windows设备注册

5.1 Azure AD Join + Intune auto-enrollment

5.1 Azure AD加入 + Intune自动注册

powershell
undefined
powershell
undefined

Check current join status

检查当前加入状态

dsregcmd /status
dsregcmd /status

Join Azure AD (user will be prompted for credentials)

加入Azure AD(用户将被提示输入凭据)

Start-Process "ms-settings:workplace"
Start-Process "ms-settings:workplace"

Verify Intune enrollment

验证Intune注册状态

Get-WmiObject -Namespace "root\cimv2\mdm\dmmap" ` -Class "MDM_DevDetail_Ext01" | Select DeviceID
undefined
Get-WmiObject -Namespace "root\cimv2\mdm\dmmap" ` -Class "MDM_DevDetail_Ext01" | Select DeviceID
undefined

5.2 Windows Autopilot hardware hash collection

5.2 Windows Autopilot硬件哈希收集

powershell
undefined
powershell
undefined

Collect hardware hash for Autopilot registration

收集硬件哈希用于Autopilot注册

Install-Script -Name Get-WindowsAutoPilotInfo -Force Get-WindowsAutoPilotInfo -OutputFile C:\temp\autopilot.csv
Install-Script -Name Get-WindowsAutoPilotInfo -Force Get-WindowsAutoPilotInfo -OutputFile C:\temp\autopilot.csv

Upload autopilot.csv to Intune > Devices > Windows Enrollment > Devices

将autopilot.csv上传至Intune > 设备 > Windows注册 > 设备

undefined
undefined

5.3 BitLocker enforcement via Group Policy or Intune

5.3 通过组策略或Intune强制启用BitLocker

powershell
undefined
powershell
undefined

Enable BitLocker on the OS drive with TPM

启用基于TPM的系统盘BitLocker加密

Enable-BitLocker -MountPoint "C:"
  -EncryptionMethod XtsAes256
-TpmProtector
Enable-BitLocker -MountPoint "C:"
  -EncryptionMethod XtsAes256
-TpmProtector

Add a recovery password and back it up to Azure AD

添加恢复密码并备份至Azure AD

Add-BitLockerKeyProtector -MountPoint "C:" -RecoveryPasswordProtector BackupToAAD-BitLockerKeyProtector -MountPoint "C:" ` -KeyProtectorId (Get-BitLockerVolume -MountPoint "C:").KeyProtector[1].KeyProtectorId
Add-BitLockerKeyProtector -MountPoint "C:" -RecoveryPasswordProtector BackupToAAD-BitLockerKeyProtector -MountPoint "C:" ` -KeyProtectorId (Get-BitLockerVolume -MountPoint "C:").KeyProtector[1].KeyProtectorId

Verify encryption status

验证加密状态

Get-BitLockerVolume | Select-Object MountPoint, VolumeStatus, EncryptionPercentage
undefined
Get-BitLockerVolume | Select-Object MountPoint, VolumeStatus, EncryptionPercentage
undefined

5.4 Windows Firewall baseline

5.4 Windows防火墙基线配置

powershell
undefined
powershell
undefined

Ensure all profiles are enabled

确保所有配置文件均已启用

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True

Block all inbound by default, allow outbound

默认阻止所有入站流量,允许出站流量

Set-NetFirewallProfile -Profile Domain,Public,Private
  -DefaultInboundAction Block
-DefaultOutboundAction Allow
Set-NetFirewallProfile -Profile Domain,Public,Private
  -DefaultInboundAction Block
-DefaultOutboundAction Allow

Allow specific inbound rules (example: RDP only from VPN subnet)

允许特定入站规则(示例:仅允许VPN子网访问RDP)

New-NetFirewallRule -DisplayName "Allow RDP from VPN"
  -Direction Inbound -Protocol TCP -LocalPort 3389
-RemoteAddress 10.0.0.0/8 -Action Allow

---
New-NetFirewallRule -DisplayName "Allow RDP from VPN"
  -Direction Inbound -Protocol TCP -LocalPort 3389
-RemoteAddress 10.0.0.0/8 -Action Allow

---

6. Security Policies — Cross-Platform

6. 跨平台安全策略

6.1 Password / passcode requirements

6.1 密码/密码码要求

xml
<!-- macOS configuration profile — password policy -->
<dict>
    <key>PayloadType</key>
    <string>com.apple.mobiledevice.passwordpolicy</string>
    <key>minLength</key>
    <integer>12</integer>
    <key>requireAlphanumeric</key>
    <true/>
    <key>maxInactivity</key>
    <integer>5</integer>
    <key>maxPINAgeInDays</key>
    <integer>90</integer>
</dict>
json
// Intune Windows password policy (JSON for Graph API)
{
  "@odata.type": "#microsoft.graph.windows10GeneralConfiguration",
  "passwordRequired": true,
  "passwordMinimumLength": 12,
  "passwordRequiredType": "alphanumeric",
  "passwordMinutesOfInactivityBeforeScreenTimeout": 5,
  "passwordExpirationDays": 90,
  "passwordBlockSimple": true
}
xml
<!-- macOS配置文件 — 密码策略 -->
<dict>
    <key>PayloadType</key>
    <string>com.apple.mobiledevice.passwordpolicy</string>
    <key>minLength</key>
    <integer>12</integer>
    <key>requireAlphanumeric</key>
    <true/>
    <key>maxInactivity</key>
    <integer>5</integer>
    <key>maxPINAgeInDays</key>
    <integer>90</integer>
</dict>
json
// Intune Windows密码策略(Graph API用JSON)
{
  "@odata.type": "#microsoft.graph.windows10GeneralConfiguration",
  "passwordRequired": true,
  "passwordMinimumLength": 12,
  "passwordRequiredType": "alphanumeric",
  "passwordMinutesOfInactivityBeforeScreenTimeout": 5,
  "passwordExpirationDays": 90,
  "passwordBlockSimple": true
}

6.2 Screen lock enforcement

6.2 锁屏强制启用

bash
undefined
bash
undefined

macOS — require password after sleep/screensaver (via script or profile)

macOS — 休眠/屏保后要求输入密码(通过脚本或配置文件)

sudo defaults write /Library/Preferences/com.apple.screensaver askForPassword -int 1 sudo defaults write /Library/Preferences/com.apple.screensaver askForPasswordDelay -int 0 sudo defaults write /Library/Preferences/com.apple.screensaver idleTime -int 300

```powershell
sudo defaults write /Library/Preferences/com.apple.screensaver askForPassword -int 1 sudo defaults write /Library/Preferences/com.apple.screensaver askForPasswordDelay -int 0 sudo defaults write /Library/Preferences/com.apple.screensaver idleTime -int 300

```powershell

Windows — lock screen after 5 minutes of inactivity

Windows — 闲置5分钟后自动锁屏

powercfg /change monitor-timeout-ac 5
powercfg /change monitor-timeout-ac 5

Registry-based enforcement

基于注册表的强制配置

Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" ` -Name "InactivityTimeoutSecs" -Value 300
undefined
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" ` -Name "InactivityTimeoutSecs" -Value 300
undefined

6.3 Encryption enforcement summary

6.3 加密强制实施汇总

OSToolVerify Command
macOSFileVault
fdesetup status
WindowsBitLocker
manage-bde -status C:
LinuxLUKS
lsblk -o NAME,FSTYPE,MOUNTPOINT | grep crypt
iOSNative (always-on with passcode)Managed via MDM profile
AndroidNative
adb shell getprop ro.crypto.state

操作系统工具验证命令
macOSFileVault
fdesetup status
WindowsBitLocker
manage-bde -status C:
LinuxLUKS
lsblk -o NAME,FSTYPE,MOUNTPOINT | grep crypt
iOS原生加密(设置密码后始终启用)通过MDM配置文件管理
Android原生加密
adb shell getprop ro.crypto.state

7. Software Deployment

7. 软件部署

7.1 macOS — Homebrew Bundle

7.1 macOS — Homebrew Bundle

ruby
undefined
ruby
undefined

Brewfile — deploy via MDM script or Git checkout

Brewfile — 通过MDM脚本或Git检出部署

tap "homebrew/bundle"
tap "homebrew/bundle"

Core tools

核心工具

brew "git" brew "gh" brew "jq" brew "wget" brew "gnupg"
brew "git" brew "gh" brew "jq" brew "wget" brew "gnupg"

Security

安全工具

brew "1password-cli" cask "1password" cask "tailscale" cask "cloudflare-warp"
brew "1password-cli" cask "1password" cask "tailscale" cask "cloudflare-warp"

Development

开发工具

cask "visual-studio-code" cask "iterm2" cask "docker" brew "node" brew "python@3.12"
cask "visual-studio-code" cask "iterm2" cask "docker" brew "node" brew "python@3.12"

Communication

通讯工具

cask "slack" cask "zoom"

```bash
cask "slack" cask "zoom"

```bash

Deploy Brewfile on a new Mac

在新Mac上部署Brewfile

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew bundle --file=/path/to/Brewfile --no-lock
undefined
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew bundle --file=/path/to/Brewfile --no-lock
undefined

7.2 Windows — winget / Chocolatey

7.2 Windows — winget / Chocolatey

powershell
undefined
powershell
undefined

winget import from a JSON manifest

winget从JSON清单导入软件包

packages.json

packages.json

@" { "Sources": [{ "Packages": [ { "PackageIdentifier": "Git.Git" }, { "PackageIdentifier": "Microsoft.VisualStudioCode" }, { "PackageIdentifier": "Docker.DockerDesktop" }, { "PackageIdentifier": "SlackTechnologies.Slack" }, { "PackageIdentifier": "Zoom.Zoom" }, { "PackageIdentifier": "Tailscale.Tailscale" }, { "PackageIdentifier": "AgileBits.1Password" }, { "PackageIdentifier": "OpenJS.NodeJS.LTS" }, { "PackageIdentifier": "Python.Python.3.12" } ], "SourceDetails": { "Name": "winget", "Type": "Microsoft.Winget.Source.Type.Microsoft" } }] } "@ | Out-File -FilePath packages.json -Encoding utf8
winget import -i packages.json --accept-package-agreements --accept-source-agreements
undefined
@" { "Sources": [{ "Packages": [ { "PackageIdentifier": "Git.Git" }, { "PackageIdentifier": "Microsoft.VisualStudioCode" }, { "PackageIdentifier": "Docker.DockerDesktop" }, { "PackageIdentifier": "SlackTechnologies.Slack" }, { "PackageIdentifier": "Zoom.Zoom" }, { "PackageIdentifier": "Tailscale.Tailscale" }, { "PackageIdentifier": "AgileBits.1Password" }, { "PackageIdentifier": "OpenJS.NodeJS.LTS" }, { "PackageIdentifier": "Python.Python.3.12" } ], "SourceDetails": { "Name": "winget", "Type": "Microsoft.Winget.Source.Type.Microsoft" } }] } "@ | Out-File -FilePath packages.json -Encoding utf8
winget import -i packages.json --accept-package-agreements --accept-source-agreements
undefined

7.3 Automatic update enforcement

7.3 自动更新强制启用

bash
undefined
bash
undefined

macOS — enable automatic updates via MDM or command

macOS — 通过MDM或命令启用自动更新

sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -bool true sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -bool true sudo softwareupdate --schedule on

```powershell
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -bool true sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticallyInstallMacOSUpdates -bool true sudo softwareupdate --schedule on

```powershell

Windows — configure Windows Update via registry

Windows — 通过注册表配置Windows更新

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
  -Name "NoAutoUpdate" -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
-Name "AUOptions" -Value 4 # 4 = Auto download and schedule install

---
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
  -Name "NoAutoUpdate" -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
-Name "AUOptions" -Value 4 # 4 = 自动下载并安排安装

---

8. Compliance Checks with osquery

8. 使用osquery进行合规检查

These queries work with Fleet, osquery standalone, or any osquery-compatible platform.
sql
-- Check disk encryption on macOS
SELECT de.encrypted, de.type, du.username
FROM disk_encryption de
JOIN disk_util du ON de.name = du.name
WHERE du.mountpoint = '/' AND de.encrypted = 1;

-- Check disk encryption on Windows
SELECT drive_letter, protection_status, conversion_status
FROM bitlocker_info
WHERE drive_letter = 'C:' AND protection_status = 1;

-- Verify firewall is enabled (macOS)
SELECT global_state, stealth_enabled, logging_enabled
FROM alf;

-- Verify firewall is enabled (Windows)
SELECT name, enabled FROM windows_firewall_profiles
WHERE enabled = 1;

-- Check OS version (macOS)
SELECT name, version, major, minor, patch
FROM os_version
WHERE major >= 14;

-- Check OS version (Windows)
SELECT name, version, build
FROM os_version
WHERE build >= '22631';

-- List users with admin privileges (macOS)
SELECT u.username, u.uid
FROM users u
JOIN user_groups ug ON u.uid = ug.uid
JOIN groups g ON ug.gid = g.gid
WHERE g.groupname = 'admin';

-- Detect unencrypted removable drives (Windows)
SELECT device_id, drive_letter, protection_status
FROM bitlocker_info
WHERE protection_status = 0;

-- Check screen lock timeout (macOS)
SELECT domain, key, value FROM preferences
WHERE domain = 'com.apple.screensaver'
  AND key = 'idleTime';

-- Verify automatic updates are enabled (macOS)
SELECT domain, key, value FROM preferences
WHERE domain = 'com.apple.SoftwareUpdate'
  AND key = 'AutomaticCheckEnabled';

这些查询适用于Fleet、独立osquery或任何兼容osquery的平台。
sql
-- 检查macOS磁盘加密状态
SELECT de.encrypted, de.type, du.username
FROM disk_encryption de
JOIN disk_util du ON de.name = du.name
WHERE du.mountpoint = '/' AND de.encrypted = 1;

-- 检查Windows磁盘加密状态
SELECT drive_letter, protection_status, conversion_status
FROM bitlocker_info
WHERE drive_letter = 'C:' AND protection_status = 1;

-- 验证macOS防火墙是否启用
SELECT global_state, stealth_enabled, logging_enabled
FROM alf;

-- 验证Windows防火墙是否启用
SELECT name, enabled FROM windows_firewall_profiles
WHERE enabled = 1;

-- 检查macOS版本
SELECT name, version, major, minor, patch
FROM os_version
WHERE major >= 14;

-- 检查Windows版本
SELECT name, version, build
FROM os_version
WHERE build >= '22631';

-- 列出macOS上拥有管理员权限的用户
SELECT u.username, u.uid
FROM users u
JOIN user_groups ug ON u.uid = ug.uid
JOIN groups g ON ug.gid = g.gid
WHERE g.groupname = 'admin';

-- 检测Windows上未加密的可移动驱动器
SELECT device_id, drive_letter, protection_status
FROM bitlocker_info
WHERE protection_status = 0;

-- 检查macOS锁屏超时设置
SELECT domain, key, value FROM preferences
WHERE domain = 'com.apple.screensaver'
  AND key = 'idleTime';

-- 验证macOS自动更新是否启用
SELECT domain, key, value FROM preferences
WHERE domain = 'com.apple.SoftwareUpdate'
  AND key = 'AutomaticCheckEnabled';

9. Remote Wipe & Lock

9. 远程擦除与锁定

9.1 macOS remote wipe (Fleet)

9.1 macOS远程擦除(Fleet)

bash
undefined
bash
undefined

Lock a device immediately with a 6-digit PIN

立即使用6位PIN锁定设备

fleetctl mdm lock --host "serial=C02X12345678"
fleetctl mdm lock --host "serial=C02X12345678"

Wipe a device (factory reset) — DESTRUCTIVE

擦除设备(恢复出厂设置)——此操作不可恢复

fleetctl mdm erase --host "serial=C02X12345678"
fleetctl mdm erase --host "serial=C02X12345678"

Or via the Fleet API

或通过Fleet API执行

curl -X POST https://fleet.yourcompany.com/api/v1/fleet/hosts/42/wipe
-H "Authorization: Bearer ${FLEET_API_TOKEN}"
undefined
curl -X POST https://fleet.yourcompany.com/api/v1/fleet/hosts/42/wipe
-H "Authorization: Bearer ${FLEET_API_TOKEN}"
undefined

9.2 Windows remote wipe (Intune)

9.2 Windows远程擦除(Intune)

powershell
undefined
powershell
undefined

Via Microsoft Graph API

通过Microsoft Graph API执行

$body = @{ keepEnrollmentData = $false keepUserData = $false } | ConvertTo-Json
Invoke-MgGraphRequest -Method POST
  -Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/{deviceId}/wipe"
-Body $body -ContentType "application/json"
undefined
$body = @{ keepEnrollmentData = $false keepUserData = $false } | ConvertTo-Json
Invoke-MgGraphRequest -Method POST
  -Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/{deviceId}/wipe"
-Body $body -ContentType "application/json"
undefined

9.3 Lost device runbook

9.3 设备丢失处理流程

text
1. Employee reports device lost/stolen via Slack #it-help or PagerDuty.
2. IT admin verifies identity (video call or manager confirmation).
3. Immediately issue remote lock command (wipe only if data-sensitive).
4. Rotate any credentials cached on the device:
   - Revoke SSO sessions (Okta/Google Workspace admin console)
   - Rotate API keys stored on the device
   - Revoke VPN certificates
5. File a police report if theft is suspected.
6. Remove device from MDM after 30 days or once replacement is shipped.
7. Update asset inventory and notify finance for insurance claim.

text
1. 员工通过Slack #it-help频道或PagerDuty上报设备丢失/被盗。
2. IT管理员验证员工身份(视频通话或经理确认)。
3. 立即发出远程锁定命令(仅在数据高度敏感时执行擦除)。
4. 轮换设备上缓存的所有凭据:
   - 撤销SSO会话(Okta/Google Workspace管理控制台)
   - 轮换设备上存储的API密钥
   - 撤销VPN证书
5. 如确认被盗,向警方报案。
6. 30天后或设备更换完成后,将设备从MDM中移除。
7. 更新资产清单并通知财务部门申请保险理赔。

10. Onboarding Automation — Zero-Touch Enrollment

10. 入职自动化——零接触注册

10.1 macOS zero-touch flow

10.1 macOS零接触流程

bash
#!/usr/bin/env bash
bash
#!/usr/bin/env bash

onboard-mac.sh — runs as a post-enrollment script via MDM

onboard-mac.sh — 通过MDM作为注册后脚本运行

set -euo pipefail
LOG="/var/log/onboarding.log" exec > >(tee -a "$LOG") 2>&1
echo "=== Starting onboarding $(date) ==="
set -euo pipefail
LOG="/var/log/onboarding.log" exec > >(tee -a "$LOG") 2>&1
echo "=== 开始入职流程 $(date) ==="

1. Install Rosetta 2 on Apple Silicon

1. 在Apple Silicon设备上安装Rosetta 2

if [[ "$(uname -m)" == "arm64" ]]; then softwareupdate --install-rosetta --agree-to-license fi
if [[ "$(uname -m)" == "arm64" ]]; then softwareupdate --install-rosetta --agree-to-license fi

2. Install Homebrew

2. 安装Homebrew

if ! command -v brew &>/dev/null; then NONINTERACTIVE=1 /bin/bash -c
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi
if ! command -v brew &>/dev/null; then NONINTERACTIVE=1 /bin/bash -c
"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi

3. Install standard tooling from Brewfile

3. 从Brewfile安装标准工具

curl -fsSL https://internal.yourcompany.com/brewfile -o /tmp/Brewfile brew bundle --file=/tmp/Brewfile --no-lock
curl -fsSL https://internal.yourcompany.com/brewfile -o /tmp/Brewfile brew bundle --file=/tmp/Brewfile --no-lock

4. Configure Git defaults

4. 配置Git默认设置

git config --global init.defaultBranch main git config --global pull.rebase true
git config --global init.defaultBranch main git config --global pull.rebase true

5. Enable FileVault (will prompt at next login)

5. 启用FileVault(下次登录时提示)

sudo fdesetup enable -defer /var/db/FileVaultDeferred.plist
-forceatlogin 0 -dontaskatlogout
sudo fdesetup enable -defer /var/db/FileVaultDeferred.plist
-forceatlogin 0 -dontaskatlogout

6. Enable firewall

6. 启用防火墙

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on

7. Set screen lock

7. 设置锁屏

defaults write com.apple.screensaver askForPassword -int 1 defaults write com.apple.screensaver askForPasswordDelay -int 0 defaults write com.apple.screensaver idleTime -int 300
defaults write com.apple.screensaver askForPassword -int 1 defaults write com.apple.screensaver askForPasswordDelay -int 0 defaults write com.apple.screensaver idleTime -int 300

8. Enroll in Tailscale VPN

8. 注册Tailscale VPN

open -a "Tailscale"
echo "=== Onboarding complete $(date) ==="
undefined
open -a "Tailscale"
echo "=== 入职流程完成 $(date) ==="
undefined

10.2 Windows zero-touch flow (Autopilot + Intune)

10.2 Windows零接触流程(Autopilot + Intune)

powershell
undefined
powershell
undefined

deploy.ps1 — assigned as an Intune PowerShell script

deploy.ps1 — 作为Intune PowerShell脚本分配

$ErrorActionPreference = "Stop" $logFile = "C:\ProgramData\onboarding.log" Start-Transcript -Path $logFile -Append
Write-Host "=== Starting onboarding $(Get-Date) ==="
$ErrorActionPreference = "Stop" $logFile = "C:\ProgramData\onboarding.log" Start-Transcript -Path $logFile -Append
Write-Host "=== 开始入职流程 $(Get-Date) ==="

1. Install winget packages

1. 安装winget软件包

$packages = @( "Git.Git", "Microsoft.VisualStudioCode", "Docker.DockerDesktop", "SlackTechnologies.Slack", "Tailscale.Tailscale", "AgileBits.1Password" )
foreach ($pkg in $packages) { Write-Host "Installing $pkg..." winget install --id $pkg --accept-package-agreements --accept-source-agreements --silent }
$packages = @( "Git.Git", "Microsoft.VisualStudioCode", "Docker.DockerDesktop", "SlackTechnologies.Slack", "Tailscale.Tailscale", "AgileBits.1Password" )
foreach ($pkg in $packages) { Write-Host "正在安装 $pkg..." winget install --id $pkg --accept-package-agreements --accept-source-agreements --silent }

2. Enable BitLocker

2. 启用BitLocker

Enable-BitLocker -MountPoint "C:" -EncryptionMethod XtsAes256 -TpmProtector Add-BitLockerKeyProtector -MountPoint "C:" -RecoveryPasswordProtector
Enable-BitLocker -MountPoint "C:" -EncryptionMethod XtsAes256 -TpmProtector Add-BitLockerKeyProtector -MountPoint "C:" -RecoveryPasswordProtector

3. Configure firewall

3. 配置防火墙

Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True Set-NetFirewallProfile -Profile Domain,Public,Private ` -DefaultInboundAction Block -DefaultOutboundAction Allow
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True Set-NetFirewallProfile -Profile Domain,Public,Private ` -DefaultInboundAction Block -DefaultOutboundAction Allow

4. Set power and lock settings

4. 设置电源与锁屏选项

powercfg /change monitor-timeout-ac 5 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" ` -Name "InactivityTimeoutSecs" -Value 300
powercfg /change monitor-timeout-ac 5 Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" ` -Name "InactivityTimeoutSecs" -Value 300

5. Enable automatic updates

5. 启用自动更新

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` -Name "AUOptions" -Value 4
Write-Host "=== Onboarding complete $(Get-Date) ===" Stop-Transcript
undefined
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" ` -Name "AUOptions" -Value 4
Write-Host "=== 入职流程完成 $(Get-Date) ===" Stop-Transcript
undefined

10.3 Onboarding checklist (for IT automation)

10.3 入职检查清单(用于IT自动化)

yaml
undefined
yaml
undefined

onboarding-checklist.yml — track in your ticketing system or Fleet

onboarding-checklist.yml — 在工单系统或Fleet中跟踪

new_hire_onboarding: pre_day_one: - Purchase and ship device via CDW/Apple Business Manager - Assign device to MDM server in ABM/Autopilot - Create accounts: Google Workspace / M365, Okta SSO, GitHub, Slack - Generate VPN invite (Tailscale, WireGuard) - Prepare welcome documentation link
day_one_automated: - Device powers on and auto-enrolls in MDM (zero-touch) - MDM pushes security profiles (encryption, firewall, password policy) - Software bundle installs automatically - User signs into SSO — all apps authenticate via SAML/OIDC - Compliance policies begin evaluation
day_one_manual: - IT schedules 15-min welcome call to verify setup - Employee confirms disk encryption enabled (fdesetup status / manage-bde) - Employee joins #it-help Slack channel - Employee completes security awareness training link
week_one_verification: - Fleet/MDM dashboard shows device as compliant - All critical policies passing (encryption, firewall, OS version) - VPN connectivity verified - MFA enrolled on all critical services

---
new_hire_onboarding: pre_day_one: - 通过CDW/Apple Business Manager采购并寄送设备 - 在ABM/Autopilot中将设备分配给MDM服务器 - 创建账户:Google Workspace / M365、Okta SSO、GitHub、Slack - 生成VPN邀请链接(Tailscale、WireGuard) - 准备欢迎文档链接
day_one_automated: - 设备开机后自动注册到MDM(零接触) - MDM推送安全配置文件(加密、防火墙、密码策略) - 自动安装软件包集合 - 用户登录SSO——所有应用通过SAML/OIDC认证 - 合规策略开始评估
day_one_manual: - IT安排15分钟欢迎通话以验证设置完成情况 - 员工确认磁盘加密已启用(使用fdesetup status / manage-bde命令) - 员工加入#it-help Slack频道 - 员工完成安全意识培训链接
week_one_verification: - Fleet/MDM仪表板显示设备合规 - 所有关键策略通过(加密、防火墙、操作系统版本) - VPN连接已验证 - 所有关键服务已启用MFA

---

Quick Reference

快速参考

TaskmacOS CommandWindows Command
Check encryption
fdesetup status
manage-bde -status C:
Enable firewall
socketfilterfw --setglobalstate on
Set-NetFirewallProfile -Enabled True
Force OS update
softwareupdate -ia
usoclient StartInstallD
Lock screen now
pmset displaysleepnow
rundll32.exe user32.dll,LockWorkStation
List MDM profiles
profiles show -type enrollment
dsregcmd /status
Check compliance
fleetctl get hosts --query "..."
fleetctl get hosts --query "..."
任务macOS命令Windows命令
检查加密状态
fdesetup status
manage-bde -status C:
启用防火墙
socketfilterfw --setglobalstate on
Set-NetFirewallProfile -Enabled True
强制操作系统更新
softwareupdate -ia
usoclient StartInstallD
立即锁屏
pmset displaysleepnow
rundll32.exe user32.dll,LockWorkStation
列出MDM配置文件
profiles show -type enrollment
dsregcmd /status
检查合规性
fleetctl get hosts --query "..."
fleetctl get hosts --query "..."