mdm-device-management
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMobile 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平台对比
| Platform | Best For | Pricing Model | Open Source | Key Strength |
|---|---|---|---|---|
| Jamf Pro | macOS / iOS fleets | Per-device/yr | No | Deepest Apple integration, DEP/ADE native |
| Microsoft Intune | Windows + M365 shops | Bundled w/ M365 E3/E5 | No | Seamless Azure AD + Autopilot |
| Kandji | macOS-first startups | Per-device/yr | No | Pre-built compliance templates, fast setup |
| Mosyle | Education & SMB Apple | Per-device/yr | No | Apple School/Business Manager integration |
| Fleet | Cross-platform, eng-led | Free (OSS) / paid cloud | Yes | osquery-powered, GitOps-friendly, API-first |
| SimpleMDM | Small Apple-only teams | Per-device/mo | No | Simple UI, quick onboarding |
| 平台 | 适用场景 | 定价模式 | 是否开源 | 核心优势 |
|---|---|---|---|---|
| Jamf Pro | macOS/iOS设备集群 | 按设备/年收费 | 否 | 最深度的Apple集成,原生支持DEP/ADE |
| Microsoft Intune | Windows + 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 mixtext
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 mix3. 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
undefinedyaml
undefineddocker-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:
undefinedversion: "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:
undefined3.2 Initial setup
3.2 初始设置
bash
undefinedbash
undefinedGenerate 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"
-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"
-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"
--email admin@yourcompany.com
--name "IT Admin"
--password "${FLEET_ADMIN_PASSWORD}"
--org-name "YourCompany"
undefineddocker 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"
--email admin@yourcompany.com
--name "IT Admin"
--password "${FLEET_ADMIN_PASSWORD}"
--org-name "YourCompany"
undefined3.3 Enroll a macOS host with fleetctl
3.3 使用fleetctl注册macOS主机
bash
undefinedbash
undefinedInstall 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
--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
--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分发或手动安装
undefinedundefined3.4 Enroll a Windows host
3.4 注册Windows主机
powershell
undefinedpowershell
undefinedDownload the Fleet osquery MSI installer
下载Fleet osquery MSI安装包
fleetctl package --type msi
--enroll-secret "$(fleetctl get enroll-secret)" `
--fleet-certificate tls/fleet.crt
--fleet-url https://fleet.yourcompany.com:8080fleetctl package --type msi
--enroll-secret "$(fleetctl get enroll-secret)" `
--fleet-certificate tls/fleet.crt
--fleet-url https://fleet.yourcompany.com:8080Install silently
静默安装
msiexec /i fleet-osquery.msi /quiet /norestart
undefinedmsiexec /i fleet-osquery.msi /quiet /norestart
undefined3.5 osquery policy examples in Fleet
3.5 Fleet中的osquery策略示例
yaml
undefinedyaml
undefinedfleet-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
undefinedbash
undefinedIn 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
undefinedfleetctl get mdm-apple
undefined4.2 Manual MDM profile enrollment (non-DEP devices)
4.2 手动MDM配置文件注册(非DEP设备)
bash
undefinedbash
undefinedGenerate 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
然后在系统设置 > 配置文件中批准
undefinedundefined4.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
undefinedbash
undefinedEnable 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
undefinedpowershell
undefinedCheck 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
undefinedGet-WmiObject -Namespace "root\cimv2\mdm\dmmap" `
-Class "MDM_DevDetail_Ext01" | Select DeviceID
undefined5.2 Windows Autopilot hardware hash collection
5.2 Windows Autopilot硬件哈希收集
powershell
undefinedpowershell
undefinedCollect 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注册 > 设备
undefinedundefined5.3 BitLocker enforcement via Group Policy or Intune
5.3 通过组策略或Intune强制启用BitLocker
powershell
undefinedpowershell
undefinedEnable BitLocker on the OS drive with TPM
启用基于TPM的系统盘BitLocker加密
Enable-BitLocker -MountPoint "C:"
-TpmProtector
-EncryptionMethod XtsAes256Enable-BitLocker -MountPoint "C:"
-TpmProtector
-EncryptionMethod XtsAes256Add 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
undefinedGet-BitLockerVolume | Select-Object MountPoint, VolumeStatus, EncryptionPercentage
undefined5.4 Windows Firewall baseline
5.4 Windows防火墙基线配置
powershell
undefinedpowershell
undefinedEnsure 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
-DefaultOutboundAction Allow
-DefaultInboundAction BlockSet-NetFirewallProfile -Profile Domain,Public,Private
-DefaultOutboundAction Allow
-DefaultInboundAction BlockAllow specific inbound rules (example: RDP only from VPN subnet)
允许特定入站规则(示例:仅允许VPN子网访问RDP)
New-NetFirewallRule -DisplayName "Allow RDP from VPN"
-RemoteAddress 10.0.0.0/8 -Action Allow
-Direction Inbound -Protocol TCP -LocalPort 3389
---New-NetFirewallRule -DisplayName "Allow RDP from VPN"
-RemoteAddress 10.0.0.0/8 -Action Allow
-Direction Inbound -Protocol TCP -LocalPort 3389
---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
undefinedbash
undefinedmacOS — 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
```powershellsudo 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
```powershellWindows — 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
undefinedSet-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
-Name "InactivityTimeoutSecs" -Value 300
undefined6.3 Encryption enforcement summary
6.3 加密强制实施汇总
| OS | Tool | Verify Command |
|---|---|---|
| macOS | FileVault | |
| Windows | BitLocker | |
| Linux | LUKS | |
| iOS | Native (always-on with passcode) | Managed via MDM profile |
| Android | Native | |
| 操作系统 | 工具 | 验证命令 |
|---|---|---|
| macOS | FileVault | |
| Windows | BitLocker | |
| Linux | LUKS | |
| iOS | 原生加密(设置密码后始终启用) | 通过MDM配置文件管理 |
| Android | 原生加密 | |
7. Software Deployment
7. 软件部署
7.1 macOS — Homebrew Bundle
7.1 macOS — Homebrew Bundle
ruby
undefinedruby
undefinedBrewfile — 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"
```bashcask "slack"
cask "zoom"
```bashDeploy 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
undefined7.2 Windows — winget / Chocolatey
7.2 Windows — winget / Chocolatey
powershell
undefinedpowershell
undefinedwinget 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
undefined7.3 Automatic update enforcement
7.3 自动更新强制启用
bash
undefinedbash
undefinedmacOS — 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
```powershellsudo 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
```powershellWindows — configure Windows Update via registry
Windows — 通过注册表配置Windows更新
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
-Name "AUOptions" -Value 4 # 4 = Auto download and schedule install
-Name "NoAutoUpdate" -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
---Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
-Name "AUOptions" -Value 4 # 4 = 自动下载并安排安装
-Name "NoAutoUpdate" -Value 0 Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
---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
undefinedbash
undefinedLock 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}"
-H "Authorization: Bearer ${FLEET_API_TOKEN}"
undefinedcurl -X POST https://fleet.yourcompany.com/api/v1/fleet/hosts/42/wipe
-H "Authorization: Bearer ${FLEET_API_TOKEN}"
-H "Authorization: Bearer ${FLEET_API_TOKEN}"
undefined9.2 Windows remote wipe (Intune)
9.2 Windows远程擦除(Intune)
powershell
undefinedpowershell
undefinedVia Microsoft Graph API
通过Microsoft Graph API执行
$body = @{
keepEnrollmentData = $false
keepUserData = $false
} | ConvertTo-Json
Invoke-MgGraphRequest -Method POST
-Body $body -ContentType "application/json"
-Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/{deviceId}/wipe"undefined$body = @{
keepEnrollmentData = $false
keepUserData = $false
} | ConvertTo-Json
Invoke-MgGraphRequest -Method POST
-Body $body -ContentType "application/json"
-Uri "https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/{deviceId}/wipe"undefined9.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 bashbash
#!/usr/bin/env bashonboard-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
"$(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
"$(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
-forceatlogin 0 -dontaskatlogout
sudo fdesetup enable -defer /var/db/FileVaultDeferred.plist
-forceatlogin 0 -dontaskatlogout
-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) ==="
undefinedopen -a "Tailscale"
echo "=== 入职流程完成 $(date) ==="
undefined10.2 Windows zero-touch flow (Autopilot + Intune)
10.2 Windows零接触流程(Autopilot + Intune)
powershell
undefinedpowershell
undefineddeploy.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
undefinedSet-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" `
-Name "AUOptions" -Value 4
Write-Host "=== 入职流程完成 $(Get-Date) ==="
Stop-Transcript
undefined10.3 Onboarding checklist (for IT automation)
10.3 入职检查清单(用于IT自动化)
yaml
undefinedyaml
undefinedonboarding-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
快速参考
| Task | macOS Command | Windows Command |
|---|---|---|
| Check encryption | | |
| Enable firewall | | |
| Force OS update | | |
| Lock screen now | | |
| List MDM profiles | | |
| Check compliance | | |
| 任务 | macOS命令 | Windows命令 |
|---|---|---|
| 检查加密状态 | | |
| 启用防火墙 | | |
| 强制操作系统更新 | | |
| 立即锁屏 | | |
| 列出MDM配置文件 | | |
| 检查合规性 | | |