functions/New-XdrEndpointConfigurationCustomCollectionRule.ps1
|
function New-XdrEndpointConfigurationCustomCollectionRule { <# .SYNOPSIS Creates a new custom collection rule for Microsoft Defender for Endpoint from a YAML file. .DESCRIPTION Creates custom collection rules for Microsoft Defender for Endpoint by importing YAML files. The YAML files should follow the schema format used by Get-XdrEndpointConfigurationCustomCollectionRule. Each file is validated before submission to ensure proper schema structure. More information about the schema can be found here: https://github.com/FalconForceTeam/TelemetryCollectionManager .PARAMETER FilePath Path to one or more YAML files containing custom collection rule definitions. Supports wildcards for batch processing. .PARAMETER Enabled Specifies whether the created rule(s) should be enabled. Default is $false. .PARAMETER BypassCache Bypasses any existing cache entries when creating the rule. Will slow down processing if multiple rules are created in succession. .PARAMETER Confirm Prompts for confirmation before creating each rule. .PARAMETER WhatIf Shows what would happen if the cmdlet runs. The cmdlet is not run. .EXAMPLE New-XdrEndpointConfigurationCustomCollectionRule -FilePath "C:\Rules\FileMonitoring.yaml" Creates a single custom collection rule from the specified YAML file. .EXAMPLE New-XdrEndpointConfigurationCustomCollectionRule -FilePath "C:\Rules\*.yaml" Creates custom collection rules from all YAML files in the specified directory. .EXAMPLE Get-ChildItem "C:\Rules" -Filter "*.yaml" | New-XdrEndpointConfigurationCustomCollectionRule Creates custom collection rules from all YAML files using pipeline input. .OUTPUTS Object Returns the created custom collection rule object(s) from the API. .NOTES Required YAML properties: - name: Rule name (string) - enabled: Rule enabled status (boolean) - platform: Target platform (Windows, Linux, macOS) - scope: Rule scope (Organization) - table: Target table (DeviceFileEvents, DeviceNetworkEvents, etc.) - actionType: Event type to collect - filters: Filter expressions object Optional YAML properties: - description: Rule description (string) #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('FullName', 'Path')] [string[]]$FilePath, [Parameter()] [bool]$Enabled = $false, [switch]$BypassCache ) begin { Update-XdrConnectionSettings # Check if ConvertFrom-Yaml is available (PowerShell 7+) if (-not (Get-Command ConvertFrom-Yaml -ErrorAction SilentlyContinue)) { # Try to import powershell-yaml module for PowerShell 5.1 if (-not (Get-Module -Name powershell-yaml -ListAvailable)) { throw "YAML parsing requires either PowerShell 7+ or the 'powershell-yaml' module. Install with: Install-Module -Name powershell-yaml" } Import-Module powershell-yaml -ErrorAction Stop } # Get current user for createdBy field $tenantContext = Get-XdrTenantContext -ErrorAction Stop -Force:$BypassCache $createdBy = $tenantContext.AuthInfo.UserName if (-not $createdBy) { throw "Unable to determine current user principal name from tenant context" } } process { foreach ($file in $FilePath) { # Resolve wildcards and get actual file paths $resolvedPaths = Resolve-Path -Path $file -ErrorAction SilentlyContinue if (-not $resolvedPaths) { Write-Error "File not found: $file" continue } foreach ($resolvedPath in $resolvedPaths) { try { Write-Verbose "Processing file: $($resolvedPath.Path)" # Read YAML content $yamlContent = Get-Content -Path $resolvedPath.Path -Raw -ErrorAction Stop # Parse YAML using ConvertFrom-Yaml $rule = ConvertFrom-Yaml -Yaml $yamlContent -ErrorAction Stop # Validate required properties $requiredProps = @('name', 'platform', 'scope', 'table', 'actionType', 'filters') foreach ($prop in $requiredProps) { if ($rule.GetEnumerator().Name -notcontains $prop) { throw "Missing required property: $prop" } } # Check if there is a rule with the same name already existing $existingRules = Get-XdrEndpointConfigurationCustomCollectionRule if ($existingRules.RuleName -contains $rule.name) { throw "A custom collection rule with the name '$($rule.name)' already exists. Choose a different name." } # Build API request body $body = @{ ruleName = $rule.name ruleDescription = if ($rule.description) { $rule.description } else { "" } isEnabled = $Enabled table = $rule.table platform = $rule.platform actionType = $rule.actionType scope = $rule.scope filters = ConvertTo-ApiFilterFormat -Filters $rule.filters tags = $null createdBy = $createdBy } | ConvertTo-Json -Depth 20 $Uri = "https://security.microsoft.com/apiproxy/mtp/mdeCustomCollection/rules" # If WhatIf is specified, output the JSON body if ($WhatIfPreference) { Write-Host "JSON Body for rule '$($rule.name)':" Write-Host $body continue } if ($PSCmdlet.ShouldProcess($rule.name, "Create custom collection rule")) { Write-Verbose "Creating custom collection rule: $($rule.name)" $result = Invoke-RestMethod -Uri $Uri -Method Post -ContentType "application/json" -Body $body -WebSession $script:session -Headers $script:headers # Clear the cache for the Get cmdlet Clear-XdrCache -CacheKey "XdrEndpointConfigurationCustomCollectionRule" -ErrorAction SilentlyContinue Write-Verbose "Successfully created rule with ID: $($result.ruleId)" Write-Host $result } } catch { Write-Error "Failed to create custom collection rule from file '$($resolvedPath.Path)': $($_.Exception.Message)" } } } } end { } } |