Skip to content

Commit 006de6a

Browse files
committed
Agregar nuevo post sobre cómo copiar condiciones de reglas DLP con PowerShell y el parámetro AdvancedRule
1 parent e9c88f3 commit 006de6a

2 files changed

Lines changed: 287 additions & 0 deletions

File tree

1.31 MB
Loading
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
---
2+
date: '2026-07-16T20:16:05+01:00'
3+
draft: false
4+
title: 'A quick way to copy the conditions of a DLP rule with PowerShell and the AdvancedRule parameter'
5+
author: 'Shellgio'
6+
categories:
7+
- Microsoft Purview
8+
tags:
9+
- Microsoft Purview
10+
- PowerShell
11+
- Data Loss Prevention
12+
description: 'Learn how to extract, clean, save, and reuse the AdvancedRule JSON from a Microsoft Purview DLP rule for backups and lab testing.'
13+
featuredimage: "../images/quick-way-copy-dlp-rules-conditions.png"
14+
---
15+
16+
Sometimes the easiest way to build a complex Microsoft Purview Data Loss Prevention rule is not to start from scratch. You may already have a rule whose conditions, classifiers, and nested logic are exactly what you need for a lab, a backup, or a similar deployment in another tenant.
17+
18+
This is where the `AdvancedRule` property can be very useful.
19+
20+
In this post, I will show you how I **extract the condition logic from an existing DLP rule**, remove a few properties that can cause portability problems, save the result as JSON, and use it with `New-DlpComplianceRule`.
21+
22+
> [!NOTE] NOTE
23+
>
24+
> This is not a full DLP policy migration method. It is a practical way to reuse the **condition tree** of a rule. Actions, policy locations, notifications, incident reports, user or group references, and other settings still need to be reviewed and configured separately.
25+
26+
## What is `AdvancedRule`?
27+
28+
Microsoft describes the `AdvancedRule` parameter as a JSON-based complex rule syntax that supports multiple `AND`, `OR`, and `NOT` operators, including nested groups.
29+
30+
In practical terms, it is a serialized representation of the logic behind conditions such as:
31+
32+
```text
33+
(Credit Card Number OR a custom sensitive information type)
34+
AND content is shared outside the organization
35+
AND NOT sender is a member of an excluded group
36+
```
37+
38+
Rebuilding this type of logic manually with individual PowerShell parameters can be difficult. Reading the `AdvancedRule` value from a rule that already works gives us a useful starting point and preserves its nested condition structure.
39+
40+
The `AdvancedRule` parameter accepts a **string containing JSON**. We will therefore deserialize that JSON into a PowerShell hashtable, clean it, and serialize it again before passing it to `New-DlpComplianceRule`.
41+
42+
## Before you begin
43+
44+
The DLP cmdlets used here are available in Security & Compliance PowerShell. Connect with an account that has the required Microsoft Purview permissions:
45+
46+
```powershell
47+
Import-Module ExchangeOnlineManagement
48+
Connect-IPPSSession -UserPrincipalName admin@contoso.com
49+
```
50+
51+
The examples below use `ConvertFrom-Json -AsHashtable`, so run them in **PowerShell 7 or later**.
52+
53+
## 1. Get the source rule and parse `AdvancedRule`
54+
55+
You can identify a DLP rule by name or GUID:
56+
57+
```powershell
58+
$sourceRule = Get-DlpComplianceRule -Identity "DLP RULE NAME OR GUID"
59+
60+
if ([string]::IsNullOrWhiteSpace($sourceRule.AdvancedRule)) {
61+
throw "The selected rule does not contain an AdvancedRule value."
62+
}
63+
64+
$advancedRuleHash = $sourceRule.AdvancedRule | ConvertFrom-Json -AsHashtable
65+
```
66+
67+
At this point, `$advancedRuleHash` is a normal PowerShell object that we can inspect and modify:
68+
69+
```powershell
70+
$advancedRuleHash | ConvertTo-Json -Depth 30
71+
```
72+
73+
The exact JSON varies depending on the rule. You will normally see a top-level version and a condition tree containing operators, subconditions, classifier groups, sensitive information types, confidence levels, and instance counts.
74+
75+
## 2. Keep an untouched backup
76+
77+
Before changing anything, I prefer to save the original value. This gives me an exact point-in-time copy for troubleshooting or comparison:
78+
79+
```powershell
80+
$sourceRule.AdvancedRule |
81+
Set-Content -Path ".\advancedrule-original.json" -Encoding utf8
82+
```
83+
84+
The original file is the better artifact for a backup. The cleaned file that we create next is intended to be a more portable starting point.
85+
86+
## 3. Remove properties recursively
87+
88+
In JSON exported from existing rules, I have found properties such as `rulePackId`, `maxconfidence`, and `minconfidence`. For my reuse scenario, I remove them before creating the destination rule:
89+
90+
- `rulePackId` is a unique identifier for a custom or built-in Sensitive Information Type (SIT) rule package. It links DLP conditions to exact classification schemas. If you try to add it to a new rule manually you'll get an error like `Unable to create advanced rule YOUR-RULE-NAME. Error: The property name 'rulepackid' specified in sensitive information is invalid.`
91+
- `maxconfidence` and `minconfidence` are legacy numeric confidence fields. Current DLP experiences use discrete confidence levels such as Low, Medium, and High.
92+
93+
Because these keys can appear at different depths, a recursive function is safer than trying to address a fixed JSON path:
94+
95+
```powershell
96+
function Remove-DlpJsonKeys {
97+
[CmdletBinding()]
98+
param(
99+
[Parameter(Mandatory)]
100+
$InputObject,
101+
102+
[string[]]$KeysToRemove = @(
103+
'maxconfidence',
104+
'minconfidence',
105+
'rulePackId'
106+
)
107+
)
108+
109+
if ($InputObject -is [System.Collections.IDictionary]) {
110+
foreach ($key in @($InputObject.Keys)) {
111+
if ($KeysToRemove -contains $key) {
112+
$InputObject.Remove($key) | Out-Null
113+
}
114+
else {
115+
Remove-DlpJsonKeys `
116+
-InputObject $InputObject[$key] `
117+
-KeysToRemove $KeysToRemove
118+
}
119+
}
120+
}
121+
elseif (
122+
$InputObject -is [System.Collections.IEnumerable] -and
123+
$InputObject -isnot [string]
124+
) {
125+
foreach ($item in $InputObject) {
126+
Remove-DlpJsonKeys `
127+
-InputObject $item `
128+
-KeysToRemove $KeysToRemove
129+
}
130+
}
131+
}
132+
```
133+
134+
Hashtables are reference types, so the function modifies the object in place. There is no need to capture a return value.
135+
136+
## 4. Clean and serialize the JSON
137+
138+
Apply the function and convert the hashtable back into JSON:
139+
140+
```powershell
141+
Remove-DlpJsonKeys -InputObject $advancedRuleHash
142+
143+
$cleanAdvancedRuleJson = $advancedRuleHash |
144+
ConvertTo-Json -Depth 30
145+
```
146+
147+
The `-Depth` parameter is important. `ConvertTo-Json` uses a much smaller default depth, while an advanced DLP condition can contain many nested levels. Without a sufficiently high value, PowerShell can truncate parts of the condition tree.
148+
149+
Validate the result before continuing:
150+
151+
```powershell
152+
if (-not (Test-Json -Json $cleanAdvancedRuleJson)) {
153+
throw "The cleaned AdvancedRule is not valid JSON."
154+
}
155+
```
156+
157+
Now save the portable copy:
158+
159+
```powershell
160+
$cleanAdvancedRuleJson |
161+
Set-Content -Path ".\advancedrule-clean.json" -Encoding utf8
162+
```
163+
164+
To load it in another session or script:
165+
166+
```powershell
167+
$cleanAdvancedRuleJson = Get-Content `
168+
-Path ".\advancedrule-clean.json" `
169+
-Raw
170+
```
171+
172+
Using `-Raw` matters because it reads the file as a single string, which is exactly what the `AdvancedRule` parameter expects.
173+
174+
## 5. Check dependencies before using another tenant
175+
176+
Valid JSON does not guarantee that every referenced object exists in the destination tenant. Before creating the rule, review the file for dependencies such as:
177+
178+
- Custom sensitive information types
179+
- Exact Data Match classifiers
180+
- Document fingerprints
181+
- Trainable classifiers
182+
- Sensitivity labels
183+
- Microsoft Entra users and groups
184+
- Tenant-specific email addresses or domains
185+
186+
For sensitive information types, you can compare what is available in the destination tenant with:
187+
188+
```powershell
189+
Get-DlpSensitiveInformationType |
190+
Select-Object Name, Id, RecommendedConfidence |
191+
Sort-Object Name
192+
```
193+
194+
Built-in classifiers are generally easier to reuse. Custom classifiers must be created or migrated first, and their identifiers may be different in the destination tenant. Treat every GUID inside the JSON as something that needs to be understood rather than blindly copied.
195+
196+
The destination DLP policy must also exist and use locations that support the conditions and actions you intend to configure.
197+
198+
## 6. Create the new DLP rule
199+
200+
The following example creates a lab rule using the copied condition logic and a simple blocking action:
201+
202+
```powershell
203+
$cleanAdvancedRuleJson = Get-Content `
204+
-Path ".\advancedrule-clean.json" `
205+
-Raw
206+
207+
$newRuleParameters = @{
208+
Name = "Lab - Copied advanced condition"
209+
Policy = "Lab DLP Policy"
210+
AdvancedRule = $cleanAdvancedRuleJson
211+
BlockAccess = $true
212+
}
213+
214+
New-DlpComplianceRule @newRuleParameters
215+
```
216+
217+
`New-DlpComplianceRule` requires condition logic and an associated action. `AdvancedRule` supplies the condition in this example; `BlockAccess` is only an illustrative action. Replace it with the behavior that is appropriate for your workload and test case.
218+
219+
If you want to reproduce more of the source rule, inspect all of its properties and explicitly map the actions you need. Do not assume they are contained in `AdvancedRule`:
220+
221+
```powershell
222+
$sourceRule | Format-List *
223+
```
224+
225+
## 7. Verify the result
226+
227+
Read the newly created rule back from Microsoft Purview and inspect its condition:
228+
229+
```powershell
230+
$newRule = Get-DlpComplianceRule `
231+
-Identity "Lab - Copied advanced condition"
232+
233+
$newRule.AdvancedRule |
234+
ConvertFrom-Json |
235+
ConvertTo-Json -Depth 30
236+
```
237+
238+
Finally, validate the behavior with representative test data and keep the destination policy in a safe test or simulation mode until you confirm that the condition, exceptions, confidence levels, instance counts, and actions behave as expected.
239+
240+
## Putting it all together
241+
242+
After defining `Remove-DlpJsonKeys` as shown earlier, the core workflow is:
243+
244+
```powershell
245+
$sourceRule = Get-DlpComplianceRule -Identity "DLP RULE NAME OR GUID"
246+
247+
if ([string]::IsNullOrWhiteSpace($sourceRule.AdvancedRule)) {
248+
throw "The selected rule does not contain an AdvancedRule value."
249+
}
250+
251+
$sourceRule.AdvancedRule |
252+
Set-Content -Path ".\advancedrule-original.json" -Encoding utf8
253+
254+
$advancedRuleHash = $sourceRule.AdvancedRule |
255+
ConvertFrom-Json -AsHashtable
256+
257+
Remove-DlpJsonKeys -InputObject $advancedRuleHash
258+
259+
$cleanAdvancedRuleJson = $advancedRuleHash |
260+
ConvertTo-Json -Depth 30
261+
262+
if (-not (Test-Json -Json $cleanAdvancedRuleJson)) {
263+
throw "The cleaned AdvancedRule is not valid JSON."
264+
}
265+
266+
$cleanAdvancedRuleJson |
267+
Set-Content -Path ".\advancedrule-clean.json" -Encoding utf8
268+
269+
$newRuleParameters = @{
270+
Name = "Lab - Copied advanced condition"
271+
Policy = "Lab DLP Policy"
272+
AdvancedRule = $cleanAdvancedRuleJson
273+
BlockAccess = $true
274+
}
275+
276+
New-DlpComplianceRule @newRuleParameters
277+
```
278+
279+
For me, this approach is especially useful when I need to preserve complex rule logic, build repeatable labs, or use an existing rule as a template. It saves time, but the JSON should still be treated as configuration code: keep the original, review every dependency, document your changes, and test before enabling enforcement.
280+
281+
## Sources
282+
283+
- [New-DlpComplianceRule](https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/new-dlpcompliancerule?view=exchange-ps)
284+
- [Get-DlpComplianceRule](https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/get-dlpcompliancerule?view=exchange-ps)
285+
- [Connect-IPPSSession](https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/connect-ippssession?view=exchange-ps)
286+
- [Learn about sensitive information types](https://learn.microsoft.com/en-us/purview/sit-sensitive-information-type-learn-about)
287+
- [Get-DlpSensitiveInformationType](https://learn.microsoft.com/en-us/powershell/module/exchangepowershell/get-dlpsensitiveinformationtype?view=exchange-ps)

0 commit comments

Comments
 (0)