DSCResources/MSFT_M365DSCGraphAPIRuleEvaluation/MSFT_M365DSCGraphAPIRuleEvaluation.psm1
Confirm-M365DSCModuleDependency -ModuleName 'M365DSCGraphAPIRuleEvaluation' function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $APIUrl, [Parameter(Mandatory = $true)] [System.String] $RuleDefinition, [Parameter()] [System.String] $InstancesProperty = 'value', [Parameter()] [System.String] $InstanceIdentifier, [Parameter()] [System.String] $RuleName, [Parameter()] [System.String] $AfterRuleCountQuery, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.Management.Automation.PSCredential] $ApplicationSecret, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [Switch] $ManagedIdentity, [Parameter()] [System.String[]] $AccessTokens ) return $null } function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $APIUrl, [Parameter(Mandatory = $true)] [System.String] $RuleDefinition, [Parameter()] [System.String] $InstancesProperty = 'value', [Parameter()] [System.String] $InstanceIdentifier, [Parameter()] [System.String] $RuleName, [Parameter()] [System.String] $AfterRuleCountQuery, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.Management.Automation.PSCredential] $ApplicationSecret, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [Switch] $ManagedIdentity, [Parameter()] [System.String[]] $AccessTokens ) # Not Implemented } function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $APIUrl, [Parameter(Mandatory = $true)] [System.String] $RuleDefinition, [Parameter()] [System.String] $InstancesProperty = 'value', [Parameter()] [System.String] $InstanceIdentifier, [Parameter()] [System.String] $RuleName, [Parameter()] [System.String] $AfterRuleCountQuery, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.Management.Automation.PSCredential] $ApplicationSecret, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [Switch] $ManagedIdentity, [Parameter()] [System.String[]] $AccessTokens ) #region Telemetry $CurrentResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' $CommandName = $MyInvocation.MyCommand $data = Format-M365DSCTelemetryParameters -ResourceName $CurrentResourceName ` -CommandName $CommandName ` -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters Write-Verbose -Message "Invoking GET {$($APIUrl)}" $uri = $APIUrl $DSCConvertedInstances = @() do { # Make the API request $response = Invoke-MgGraphRequest -Uri $uri -Method GET # Add the current page of results to the array $DSCConvertedInstances += $response.$InstancesProperty # Check if there's a next page $uri = $response.'@odata.nextLink' } while ($uri) Write-Verbose -Message 'Querying DSC Objects for invalid instances based on the specified Rule Definition.' if ($RuleDefinition -eq '*') { [Array]$instances = $DSCConvertedInstances Write-Verbose -Message "Identified {$($instances.Length)} instances matching rule." } else { $queryBlock = [Scriptblock]::Create($RuleDefinition) [Array]$instances = $DSCConvertedInstances | Where-Object -FilterScript $queryBlock Write-Verbose -Message "Identified {$($instances.Length)} instances matching rule." } $result = ($instances.Length - $DSCConvertedInstances.Length) -eq 0 $message = [System.Text.StringBuilder]::New() [void]$message.AppendLine('<M365DSCGraphAPIRuleEvaluation>') [void]$message.AppendLine(" <RuleName>$RuleName</RuleName>") [void]$message.AppendLine(" <ResourceName>$ResourceTypeName</ResourceName>") [void]$message.AppendLine(" <RuleDefinition>$RuleDefinition</RuleDefinition>") if (-not [System.String]::IsNullOrEmpty($AfterRuleCountQuery)) { [void]$message.AppendLine(' <AfterRuleCount>') [void]$message.AppendLine(" <Query>$AfterRuleCountQuery</Query>") Write-Verbose -Message 'Checking the After Rule Count Query' $afterRuleCountQueryString = "`$instances.Length $AfterRuleCountQuery" $afterRuleCountQueryBlock = [Scriptblock]::Create($afterRuleCountQueryString) $result = [Boolean](Invoke-Command -ScriptBlock $afterRuleCountQueryBlock) if ($InstanceIdentifier) { [array]$validInstances = $instances.$InstanceIdentifier [array]$invalidInstances = $DSCConvertedInstances.$InstanceIdentifier | Where-Object -FilterScript { $_ -notin $validInstances } } if (-not $result) { [void]$message.AppendLine(' <MetQuery>False</MetQuery>') [void]$message.AppendLine(' </AfterRuleCount>') if ($validInstances.Count -gt 0) { [void]$message.AppendLine(' <Match>') foreach ($validInstance in $validInstances) { [void]$message.AppendLine(" <$InstanceIdentifier>$validInstance</$InstanceIdentifier>") } [void]$message.AppendLine(' </Match>') } else { [void]$message.AppendLine(' <Match></Match>') } } else { [void]$message.AppendLine(' <MetQuery>True</MetQuery>') [void]$message.AppendLine(' </AfterRuleCount>') [void]$message.AppendLine(' <Match>') foreach ($validInstance in $validInstances) { [void]$message.AppendLine(" <InstanceIdentifier>[$ResourceTypeName]$validInstance</InstanceIdentifier>") } [void]$message.AppendLine(' </Match>') } } else { [void]$message.AppendLine(' <AfterRuleCount></AfterRuleCount>') $compareInstances = @() if ($compareInstances.Count -gt 0) { [array]$validInstances = $($compareInstances | Where-Object -FilterScript { $_.SideIndicator -eq '==' }).InputObject [array]$invalidInstances = $($compareInstances | Where-Object -FilterScript { $_.SideIndicator -eq '<=' }).InputObject } else { [array]$validInstances = @() [array]$invalidInstances = [array]$DSCConvertedInstances.$InstanceIdentifier } if ($validInstances.Count -gt 0) { [void]$message.AppendLine(' <Match>') foreach ($validInstance in $validInstances) { [void]$message.AppendLine(" <$InstanceIdentifier>$validInstance</$InstanceIdentifier>") } [void]$message.AppendLine(' </Match>') } else { [void]$message.AppendLine(' <Match></Match>') } } # Log drifts for each invalid instances found. if ($invalidInstances.Count -gt 0) { [void]$message.AppendLine(' <NotMatch>') foreach ($invalidInstance in $invalidInstances) { [void]$message.AppendLine(" <$InstanceIdentifier>$invalidInstance</$InstanceIdentifier>") } [void]$message.AppendLine(' </NotMatch>') } else { [void]$message.AppendLine(' <NotMatch></NotMatch>') } [void]$message.AppendLine('</M365DSCGraphAPIRuleEvaluation>') $Parameters = @{ Message = $message.ToString() EventType = 'RuleEvaluation' EventID = 1 Source = $CurrentResourceName } if (-not $result) { $Parameters.Add('EntryType', 'Warning') } else { $Parameters.Add('EntryType', 'Information') } Add-M365DSCEvent @Parameters Write-Verbose -Message "Test-TargetResource returned $result" $Script:exportedInstance = $null return $result } function Export-TargetResource { [CmdletBinding()] [OutputType([System.String])] param ( [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.String] $ApplicationId, [Parameter()] [System.String] $TenantId, [Parameter()] [System.Management.Automation.PSCredential] $ApplicationSecret, [Parameter()] [System.String] $CertificateThumbprint, [Parameter()] [Switch] $ManagedIdentity, [Parameter()] [System.String[]] $AccessTokens ) Write-M365DSCHost -Message "`r`n" -DeferWrite return $null } Export-ModuleMember -Function *-TargetResource |