mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Article: Shorten, link out - Update migrating-intune-policies-to-flee… (#42113)
…t-csp-converter.md
This commit is contained in:
parent
35f1b2d96c
commit
0004e0f240
1 changed files with 3 additions and 146 deletions
|
|
@ -6,33 +6,6 @@ Migrating Windows configuration policies from Microsoft Intune to Fleet doesn't
|
|||
|
||||
If you're new to Windows CSPs in Fleet, start with [Creating Windows configuration profiles (CSPs)](https://fleetdm.com/guides/creating-windows-csps) first. That guide explains the SyncML format, registry lookups, and how Fleet applies profiles to devices.
|
||||
|
||||
## How it works
|
||||
|
||||
The converter takes an Intune JSON policy export and produces SyncML XML files for each policy setting, ready to upload to Fleet as [custom OS settings](https://fleetdm.com/guides/custom-os-settings).
|
||||
|
||||
It does this in four steps:
|
||||
|
||||
1. **Policy extraction** — Recursively parses the Intune JSON, including nested choice settings and their child configurations.
|
||||
2. **Registry lookup** — Queries the Windows CSP NodeCache registry (`HKLM:\SOFTWARE\Microsoft\Provisioning\NodeCache\CSP\Device\MS DM Server\Nodes`) to find the exact `NodeURI` path with proper TitleCase casing — which Windows CSPs require.
|
||||
3. **Format detection** — Determines whether each setting should use `bool`, `int`, or `chr` SyncML format, based on the policy type and Microsoft's CSP documentation.
|
||||
4. **Value resolution** — For policies where Intune stores `ExpectedValue = -1` (unset), a resolver map of PowerShell expressions queries the current system state to determine the correct value.
|
||||
|
||||
Each setting becomes a SyncML `<Replace>` block:
|
||||
|
||||
```xml
|
||||
<Replace>
|
||||
<Item>
|
||||
<Meta>
|
||||
<Format xmlns="syncml:metinf">bool</Format>
|
||||
</Meta>
|
||||
<Target>
|
||||
<LocURI>./Vendor/MSFT/Firewall/MdmStore/PrivateProfile/EnableFirewall</LocURI>
|
||||
</Target>
|
||||
<Data>true</Data>
|
||||
</Item>
|
||||
</Replace>
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running the converter:
|
||||
|
|
@ -66,44 +39,8 @@ Open PowerShell as Administrator on your Intune-enrolled Windows host and run:
|
|||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "C:\Path\To\YourPolicy.json"
|
||||
```
|
||||
|
||||
### Common usage patterns
|
||||
|
||||
Basic conversion (individual XML files per policy):
|
||||
```powershell
|
||||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "MyFirewallPolicy.json"
|
||||
```
|
||||
|
||||
Create a single merged XML file:
|
||||
```powershell
|
||||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "MyPolicy.json" -MergeXml -OutputPath "C:\Fleet\CSPs"
|
||||
```
|
||||
|
||||
Dry run — analyze without creating files:
|
||||
```powershell
|
||||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "MyPolicy.json" -DryRun
|
||||
```
|
||||
|
||||
Debug mode — verbose output for troubleshooting:
|
||||
```powershell
|
||||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "MyPolicy.json" -DebugMode
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|-------------|---------|
|
||||
| `JsonPath` | Path to Intune policy JSON export | *Required* |
|
||||
| `ResolverMapPath` | Path to `resolver-map.json` | `C:\CSPConverter\resolver-map.json` |
|
||||
| `OutputPath` | Directory for output XML files | `C:\CSPConverter\Output` |
|
||||
| `LogPath` | Path for conversion log CSV | `C:\CSPConverter\ConversionLog.csv` |
|
||||
| `DebugMode` | Verbose debug output | `$false` |
|
||||
| `DryRun` | Analyze only, no files created | `$false` |
|
||||
| `MergeXml` | Merge all policies into one XML file | `$false` |
|
||||
|
||||
### Step 3: Review the results
|
||||
|
||||
### Console summary
|
||||
|
||||
When the script finishes, it prints a summary:
|
||||
|
||||
```
|
||||
|
|
@ -123,24 +60,11 @@ Not Found: 2
|
|||
| Skipped | No value could be determined (no resolver, no usable suffix) |
|
||||
| Not Found | No matching entry in the CSP NodeCache registry |
|
||||
|
||||
### Conversion log
|
||||
|
||||
A CSV log is saved to `C:\CSPConverter\ConversionLog.csv` (or your specified `-LogPath`). Open it in Excel or any CSV viewer to review every policy:
|
||||
|
||||
| Column | Description |
|
||||
|--------|-------------|
|
||||
| `Setting` | Original Intune `settingDefinitionId` |
|
||||
| `NodeUri` | The resolved CSP path used in the XML |
|
||||
| `Status` | Exported / Resolved / Skipped / Not Found / Error |
|
||||
| `Value` | The data value written into `<Data>` |
|
||||
| `Notes` | Format type and any resolution details |
|
||||
|
||||
Review `Not Found` and `Skipped` rows carefully — these are the policies that didn't convert and will need manual attention.
|
||||
|
||||
### Output files
|
||||
|
||||
Individual XML files are saved to `C:\CSPConverter\Output\` by default. Each file is named after the sanitized `NodeUri` path. If you used `-MergeXml`, you'll find a single `MergedPolicies.xml` instead.
|
||||
|
||||
> **Important:** For troubleshooting tips and more information on how this works, check out the [`intune-to-fleet` README](https://github.com/tux234/intune-to-fleet).
|
||||
|
||||
### Step 4: Upload to Fleet
|
||||
|
||||
1. Review each output XML file. Verify the `<LocURI>` and `<Data>` values look correct for your environment.
|
||||
|
|
@ -149,75 +73,8 @@ Individual XML files are saved to `C:\CSPConverter\Output\` by default. Each fil
|
|||
|
||||
Fleet will deploy the profile to matching Windows devices on their next MDM check-in.
|
||||
|
||||
> **Tip:** Use a small test group or canary team in Fleet before rolling out converted profiles broadly. Even a "Resolved" policy may need tweaking if the resolver returned a value that doesn't match your intended configuration.
|
||||
> Use a small test group or canary team in Fleet before rolling out converted profiles broadly. Even a "Resolved" policy may need tweaking if the resolver returned a value that doesn't match your intended configuration.
|
||||
|
||||
## Resolver map
|
||||
|
||||
The `resolver-map.json` file handles the `ExpectedValue = -1` edge case — policies where Intune didn't explicitly store the enforced value in the registry. The resolver map contains PowerShell expressions that query the current system state at conversion time.
|
||||
|
||||
Built-in resolvers cover common scenarios including:
|
||||
- Windows Firewall profiles (`EnableFirewall`, `AllowLocalPolicyMerge`, etc.)
|
||||
- Defender settings (`RealTimeProtection`, `CloudProtection`, `TamperProtection`)
|
||||
- BitLocker (`RequireDeviceEncryption`, `RequireTPM`)
|
||||
- SmartScreen, DeviceLock, Privacy, Update, and System policies
|
||||
|
||||
**To add a custom resolver**, add an entry to `resolver-map.json` where the key is the last segment of the CSP path and the value is a PowerShell expression returning `1` (enabled) or `0` (disabled):
|
||||
|
||||
```json
|
||||
{
|
||||
"YourPolicyName": "try { if ((Get-ItemPropertyValue -Path 'HKLM:\\...' -Name 'PolicyValue') -eq 1) { 1 } else { 0 } } catch { 0 }"
|
||||
}
|
||||
```
|
||||
|
||||
## Extending the tool
|
||||
|
||||
### Adding boolean format policies
|
||||
|
||||
Most policies use integer format (`0` / `1`), but some Windows CSPs require `true` / `false` boolean values. If you find a policy is being written as `int` when it should be `bool`, add a wildcard pattern to the `$booleanFormatPolicies` array in the `Get-SyncMLFormatAndData` function:
|
||||
|
||||
```powershell
|
||||
$booleanFormatPolicies = @(
|
||||
# ... existing patterns ...
|
||||
"*your*custom*policy*pattern*"
|
||||
)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "No match found for NodeUri"
|
||||
|
||||
The policy wasn't found in the CSP NodeCache registry. This means either:
|
||||
- The policy isn't supported on your Windows version.
|
||||
- The policy was never applied to the device via Intune (the NodeCache is only populated for settings that have been pushed and applied).
|
||||
|
||||
Try running the script on a Windows host where that specific policy has been actively enforced by Intune.
|
||||
|
||||
### "Resolver execution failed"
|
||||
|
||||
A resolver map entry failed to execute. Check that:
|
||||
- The required PowerShell modules are installed (e.g., `Get-MpPreference` requires Windows Defender).
|
||||
- The PowerShell expression syntax in `resolver-map.json` is valid.
|
||||
- The script is running with sufficient privileges.
|
||||
|
||||
### Policies convert with unexpected values
|
||||
|
||||
Use debug mode to trace the processing of a specific policy:
|
||||
|
||||
```powershell
|
||||
.\Convert-IntuneToFleetCSP.ps1 -JsonPath "MyPolicy.json" -DebugMode -DryRun
|
||||
```
|
||||
|
||||
Debug output shows the registry lookup result, format detection logic, and the value determination for each setting. No files are created when combined with `-DryRun`.
|
||||
|
||||
### Profile fails to apply in Fleet
|
||||
|
||||
If Fleet reports a profile error after upload, check the Windows MDM event log on an affected device:
|
||||
|
||||
```powershell
|
||||
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin'; Level=2} -MaxEvents 15 | Format-Table -Wrap
|
||||
```
|
||||
|
||||
The most common cause is a `<Format>` mismatch — the CSP expects `bool` but received `int`, or vice versa. Cross-reference the CSP path in [Microsoft's documentation](https://learn.microsoft.com/en-us/windows/client-management/mdm/) to confirm the expected format.
|
||||
|
||||
## What this tool doesn't cover
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue