Private/PolicyHelper.ps1
|
<# .SYNOPSIS Policy and rule helper functions for DLP policy operations. .DESCRIPTION This file contains functions for working with DLP policies and rules including pattern matching, configuration file reading, content loading, and rule updates. .NOTES Internal module file - not exported to users. Functions are available to all module cmdlets. #> function Get-MatchingPolicies { <# .SYNOPSIS Gets DLP policies matching a wildcard pattern. .DESCRIPTION Retrieves all DLP compliance policies that match the specified pattern. Supports wildcard patterns using * for flexible matching. .PARAMETER Pattern The pattern to match against policy names. Supports wildcards: * matches any characters. Examples: "GDPR*", "*PII*", "Test Policy" .OUTPUTS Microsoft.Office.CompliancePolicy.PolicySync.PublishedPolicy[] Returns array of matching DLP compliance policies. .EXAMPLE $policies = Get-MatchingPolicies -Pattern "GDPR*" # Gets all policies starting with "GDPR" .EXAMPLE $policies = Get-MatchingPolicies -Pattern "*" # Gets all policies .EXAMPLE $policies = Get-MatchingPolicies -Pattern "Test Policy" # Gets exact match for "Test Policy" #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Pattern ) Write-Verbose "Searching for policies matching pattern: $Pattern" try { $allPolicies = Get-DlpCompliancePolicy -ErrorAction Stop # Convert wildcard pattern to regex $regexPattern = '^' + [regex]::Escape($Pattern).Replace('\*', '.*') + '$' $matchingPolicies = $allPolicies | Where-Object { $_.Name -match $regexPattern } Write-Verbose "Found $($matchingPolicies.Count) matching policies" return $matchingPolicies } catch { throw "Failed to retrieve policies: $($_.Exception.Message)" } } function Get-MatchingRules { <# .SYNOPSIS Gets DLP rules within a policy matching a wildcard pattern. .DESCRIPTION Retrieves all DLP compliance rules for a specified policy that match the specified pattern. Supports wildcard patterns using * for flexible matching. .PARAMETER PolicyName The name of the policy containing the rules. .PARAMETER Pattern The pattern to match against rule names. Supports wildcards: * matches any characters. Examples: "High*", "*Volume*", "Specific Rule" .OUTPUTS Microsoft.Office.CompliancePolicy.PolicySync.PublishedRule[] Returns array of matching DLP compliance rules. .EXAMPLE $rules = Get-MatchingRules -PolicyName "GDPR Enhanced" -Pattern "High*" # Gets all rules starting with "High" in the GDPR Enhanced policy .EXAMPLE $rules = Get-MatchingRules -PolicyName "PII Detection" -Pattern "*" # Gets all rules in the policy #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$PolicyName, [Parameter(Mandatory = $true, Position = 1)] [string]$Pattern ) Write-Verbose "Searching for rules in policy '$PolicyName' matching pattern: $Pattern" try { $allRules = Get-DlpComplianceRule -Policy $PolicyName -ErrorAction Stop # Convert wildcard pattern to regex $regexPattern = '^' + [regex]::Escape($Pattern).Replace('\*', '.*') + '$' $matchingRules = $allRules | Where-Object { $_.Name -match $regexPattern } Write-Verbose "Found $($matchingRules.Count) matching rules" return $matchingRules } catch { throw "Failed to retrieve rules for policy '$PolicyName': $($_.Exception.Message)" } } function Read-ConfigurationFile { <# .SYNOPSIS Reads and validates a CSV configuration file. .DESCRIPTION Reads a CSV configuration file, filters out comments and empty lines, and validates that required columns are present. Used for bulk update operations on DLP policies and rules. .PARAMETER FilePath The path to the CSV configuration file. .OUTPUTS System.Object[] Returns array of configuration objects from the CSV file. .EXAMPLE $config = Read-ConfigurationFile -FilePath ".\config\update-config.csv" foreach ($entry in $config) { Write-Host "Policy: $($entry.PolicyName), Rule: $($entry.RuleName)" } .NOTES Expected CSV columns: PolicyName, RuleName, PolicyTipFile, EmailBodyFile, NotifyUser Lines starting with # are treated as comments and ignored. Empty lines are ignored. #> [CmdletBinding()] param( [Parameter(Mandatory = $true, Position = 0)] [string]$FilePath ) Write-Verbose "Reading configuration from: $FilePath" if (-not (Test-Path $FilePath)) { throw "Configuration file not found: $FilePath" } try { # Import CSV, filtering out comment lines and empty lines $rawContent = Get-Content $FilePath -Encoding UTF8 $filteredContent = $rawContent | Where-Object { $_ -notmatch '^\s*#' -and $_ -notmatch '^\s*$' } # Convert to CSV $config = $filteredContent | ConvertFrom-Csv if ($null -eq $config -or $config.Count -eq 0) { throw "Configuration file is empty or contains no valid entries" } # Validate required columns $requiredColumns = @('PolicyName', 'RuleName', 'PolicyTipFile', 'EmailBodyFile', 'NotifyUser') $firstRow = $config[0] $missingColumns = $requiredColumns | Where-Object { -not $firstRow.PSObject.Properties.Name.Contains($_) } if ($missingColumns) { throw "Configuration file missing required columns: $($missingColumns -join ', ')" } Write-Verbose "Loaded $($config.Count) configuration entries" return $config } catch { throw "Failed to read configuration file: $($_.Exception.Message)" } } function Get-ContentFromFile { <# .SYNOPSIS Reads content from a file in the module's Templates directory. .DESCRIPTION Reads the full content of a template file (HTML, text, etc.) from the module's Templates directory structure. Handles path resolution relative to the module root. .PARAMETER FilePath The relative path to the content file within the Templates directory. Example: "PolicyTips\simulation-tip.html" or "EmailBodies\standard-notification.html" .OUTPUTS System.String Returns the full content of the file as a string. .EXAMPLE $html = Get-ContentFromFile -FilePath "PolicyTips\simulation-tip.html" .EXAMPLE $email = Get-ContentFromFile -FilePath "EmailBodies\standard-notification.html" .NOTES This function looks for files in the module's Templates directory. For direct template path resolution, use Get-TemplateFile from Common.ps1. #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory = $true, Position = 0)] [string]$FilePath ) Write-Verbose "Reading content from: $FilePath" # Get module root directory (parent of Private folder) $moduleRoot = Split-Path -Parent $PSScriptRoot # Build full path to template file $fullPath = Join-Path $moduleRoot "Templates" $FilePath if (-not (Test-Path $fullPath)) { throw "Content file not found: $fullPath" } try { $content = Get-Content $fullPath -Raw -Encoding UTF8 Write-Verbose "Read $($content.Length) characters from file" return $content } catch { throw "Failed to read content file '$fullPath': $($_.Exception.Message)" } } function New-DLPRuleUpdateParams { <# .SYNOPSIS Creates parameter hashtable for DLP rule updates. .DESCRIPTION Builds a hashtable of parameters for Set-DlpComplianceRule based on provided notification settings. Only includes parameters that have values, allowing selective updates. .PARAMETER RuleIdentity The identity (name or GUID) of the rule to update. .PARAMETER PolicyTipContent Optional. The HTML content for the policy tip. .PARAMETER EmailBodyContent Optional. The HTML content for the email body. .PARAMETER NotifyUser Optional. Who to notify. Values: SiteAdmin, LastModifier, Owner, or specific email addresses. .PARAMETER RemoveNotifications If specified, clears all notification settings. .OUTPUTS System.Collections.Hashtable Returns hashtable suitable for splatting to Set-DlpComplianceRule. .EXAMPLE $params = New-DLPRuleUpdateParams -RuleIdentity "Rule1" -PolicyTipContent $tip -NotifyUser "SiteAdmin" Set-DlpComplianceRule @params .NOTES This function helps centralize parameter building logic and ensures consistent parameter handling across update operations. #> [CmdletBinding()] [OutputType([hashtable])] param( [Parameter(Mandatory = $true)] [string]$RuleIdentity, [Parameter(Mandatory = $false)] [string]$PolicyTipContent, [Parameter(Mandatory = $false)] [string]$EmailBodyContent, [Parameter(Mandatory = $false)] [string]$NotifyUser, [Parameter(Mandatory = $false)] [switch]$RemoveNotifications ) $params = @{ Identity = $RuleIdentity } if ($RemoveNotifications) { # Clear notification settings $params['NotifyUser'] = @() $params['NotifyPolicyTipCustomText'] = "" $params['NotifyEmailCustomText'] = "" } else { # Add parameters only if they have values if (-not [string]::IsNullOrWhiteSpace($PolicyTipContent)) { $params['NotifyPolicyTipCustomText'] = $PolicyTipContent } if (-not [string]::IsNullOrWhiteSpace($EmailBodyContent)) { $params['NotifyEmailCustomText'] = $EmailBodyContent } if (-not [string]::IsNullOrWhiteSpace($NotifyUser)) { # Parse comma-separated values $notifyUserArray = $NotifyUser -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_ } if ($notifyUserArray.Count -gt 0) { $params['NotifyUser'] = $notifyUserArray } } } Write-Verbose "Built update parameters with $($params.Keys.Count) keys" return $params } |