Skip to main content

Key Rollover and Labeling Guide

Security add-in for Microsoft 365​

Using DKE introduces a specific challenge:
Automatic labeling in SharePoint does not work with DKE-protected labels.

This means files must be labeled manually or via alternative methods before migration, to ensure Microsoft 365 cannot read the contents.

Potential Solutions​

Here are several ways to apply the required labels to files:

  1. Manual Labeling via the Purview Label Client
  2. Azure Information Protection (AIP) Scanner
  3. PowerShell labeling files

1. Manual Labeling​

Involves selecting individual files or folders in File Explorer and applying the appropriate label.

Downside:
Limited logging in case of errors, and files must be checked one-by-one — very time-consuming and unsuitable for large migrations.

2. AIP Scanner​

A tool installed on-premises to apply labels automatically to files on file shares or SharePoint On-Premises, based on defined policies.

Advantages:
Great for larger environments or where labeling needs to be extended to on-premises setups.

Disadvantage:
In my case, with only a small local drive involved in the migration, the implementation overhead was too high.

3. PowerShell-Based Labeling​

Due to the limitations above, I chose to label files using PowerShell.

Requirements:

  • A client with PowerShell and the Purview Label Client installed
  • An app registration in Entra ID (formerly Azure Active Directory)

Limitations:

  • MSG files (Outlook messages) cannot be labeled via PowerShell
  • Password-protected or certificate-signed PDFs can't be labeled either (Limitation of the label system itself, not PowerShell)

The PowerShell Challenge​

Using standard PowerShell commands as per Microsoft documentation led to PowerShell freezing or running indefinitely.
Here is an example of a command that failed::

Get-FileStatus -Path \\Finance\Projects\ | Where-Object {$_.IsLabeled -eq $False} | Set-FileLabel -LabelId d9f23ae3-4321-4321-4321-f515f824c57b

Microsoft recommends adding the following for garbage collection:

[GC]::Collect()
[GC]::WaitForPendingFinalizers()

Our testing has proven that the above is not sufficient and additional work is required to reliably label files using a retry mechanism and job-based processing

Label File with PowerShell​

Get-ChildItem -Path \\Finance\Projects\ -Recurse -File | ForEach-Object {
try {
$maxRetries = 3
$retryCount = 0
$setSuccess = $false

while (-not $setSuccess -and $retryCount -lt $maxRetries) {
$retryCount++
$jobsetlabel = Start-Job -ScriptBlock {
param ($fileName, $DKELabelId)
Set-FileLabel -FileName $fileName -LabelId $DKELabelId
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
return $true
} -ArgumentList $_.FullName, "d9f23ae3-4321-4321-4321-f515f824c57b"

$finishedsetlabel = $jobsetlabel | Wait-Job -Timeout 10 | Receive-Job

if ($finishedsetlabel) {
$setSuccess = $true
Write-Host "Label set successfully for $($_.FullName) on attempt $retryCount." -ForegroundColor Green
}
}
}
catch {
Write-Host "Failed to set label after $maxRetries attempts for $($_.FullName)." -ForegroundColor Red
}
}

Script Highlights:​

  • Retry mechanism: Tries up to 3 times per file
  • Job-based execution: Each file is labeled in a separate job to avoid resource issues
  • Memory cleanup: Uses [GC]::Collect() and [GC]::WaitForPendingFinalizers() after each job
  • Timeout control: Prevents hanging by using Wait-Job -Timeout 10

With this approach, I successfully labeled all relevant files without PowerShell freezing or running indefinitely.

Additional Script for Pre-Migration Audit​

To ensure all files were correctly labeled before migration, I also wrote a script that read the label of each file and logged the results to a CSV. This allowed for manual review and adjustments where needed.

Need help?
Get started with CloudHSM.
Other questions?Ask Sales.
Feedback
Need help?