diff --git a/CHANGELOG.md b/CHANGELOG.md index a795685f0e..0569f040ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ * IntuneDeviceEnrollmentStatusPageWindows10 * Return all authentication methods when retrieving the policies otherwise it may fail deducing the OrganizationName via TenantId +* IntuneDeviceRemediation + * Initial Release + FIXES [#4159](https://github.com/microsoft/Microsoft365DSC/issues/4159) * SPOTenantCdnPolicy * If properties in the tenant are empty then export them as empty arrays instead of null strings, missed while fixing #4658 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.psm1 new file mode 100644 index 0000000000..84faf65371 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.psm1 @@ -0,0 +1,787 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DetectionScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DetectionScriptParameters, + + [Parameter()] + [ValidateSet('deviceHealthScript','managedInstallerScript')] + [System.String] + $DeviceHealthScriptType, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.Boolean] + $EnforceSignatureCheck, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + $RemediationScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RemediationScriptParameters, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $RunAs32Bit, + + [Parameter()] + [ValidateSet('system','user')] + [System.String] + $RunAsAccount, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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 + ) + + try + { + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $getValue = $null + #region resource generator code + $getValue = Get-MgBetaDeviceManagementDeviceHealthScript -DeviceHealthScriptId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Device Remediation with Id {$Id}" + + if (-Not [string]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementDeviceHealthScript ` + -Filter "DisplayName eq '$DisplayName'" ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { ` + $_.DeviceHealthScriptType -eq "deviceHealthScript" ` + } + if ($null -ne $getValue) + { + $getValue = Get-MgBetaDeviceManagementDeviceHealthScript -DeviceHealthScriptId $getValue.Id + } + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Device Remediation with DisplayName {$DisplayName}" + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Device Remediation with Id {$Id} and DisplayName {$DisplayName} was found." + + #region resource generator code + $complexDetectionScriptParameters = @() + foreach ($currentDetectionScriptParameters in $getValue.detectionScriptParameters) + { + $myDetectionScriptParameters = @{} + $myDetectionScriptParameters.Add('ApplyDefaultValueWhenNotAssigned', $currentDetectionScriptParameters.applyDefaultValueWhenNotAssigned) + $myDetectionScriptParameters.Add('Description', $currentDetectionScriptParameters.description) + $myDetectionScriptParameters.Add('IsRequired', $currentDetectionScriptParameters.isRequired) + $myDetectionScriptParameters.Add('Name', $currentDetectionScriptParameters.name) + $myDetectionScriptParameters.Add('DefaultValue', $currentDetectionScriptParameters.defaultValue) + if ($null -ne $currentDetectionScriptParameters.'@odata.type') + { + $myDetectionScriptParameters.Add('odataType', $currentDetectionScriptParameters.'@odata.type'.toString()) + } + if ($myDetectionScriptParameters.values.Where({$null -ne $_}).count -gt 0) + { + $complexDetectionScriptParameters += $myDetectionScriptParameters + } + } + + $complexRemediationScriptParameters = @() + foreach ($currentRemediationScriptParameters in $getValue.remediationScriptParameters) + { + $myRemediationScriptParameters = @{} + $myRemediationScriptParameters.Add('ApplyDefaultValueWhenNotAssigned', $currentRemediationScriptParameters.applyDefaultValueWhenNotAssigned) + $myRemediationScriptParameters.Add('Description', $currentRemediationScriptParameters.description) + $myRemediationScriptParameters.Add('IsRequired', $currentRemediationScriptParameters.isRequired) + $myRemediationScriptParameters.Add('Name', $currentRemediationScriptParameters.name) + $myRemediationScriptParameters.Add('DefaultValue', $currentRemediationScriptParameters.defaultValue) + if ($null -ne $currentRemediationScriptParameters.'@odata.type') + { + $myRemediationScriptParameters.Add('odataType', $currentRemediationScriptParameters.'@odata.type'.toString()) + } + if ($myRemediationScriptParameters.values.Where({$null -ne $_}).count -gt 0) + { + $complexRemediationScriptParameters += $myRemediationScriptParameters + } + } + #endregion + + #region resource generator code + $enumDeviceHealthScriptType = $null + if ($null -ne $getValue.DeviceHealthScriptType) + { + $enumDeviceHealthScriptType = $getValue.DeviceHealthScriptType.ToString() + } + + $enumRunAsAccount = $null + if ($null -ne $getValue.RunAsAccount) + { + $enumRunAsAccount = $getValue.RunAsAccount.ToString() + } + #endregion + + $results = @{ + #region resource generator code + Description = $getValue.Description + DetectionScriptContent = [System.Convert]::ToBase64String($getValue.DetectionScriptContent) + DetectionScriptParameters = $complexDetectionScriptParameters + DeviceHealthScriptType = $enumDeviceHealthScriptType + DisplayName = $getValue.DisplayName + EnforceSignatureCheck = $getValue.EnforceSignatureCheck + Publisher = $getValue.Publisher + RemediationScriptContent = [System.Convert]::ToBase64String($getValue.RemediationScriptContent) + RemediationScriptParameters = $complexRemediationScriptParameters + RoleScopeTagIds = $getValue.RoleScopeTagIds + RunAs32Bit = $getValue.RunAs32Bit + RunAsAccount = $enumRunAsAccount + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + #endregion + } + $assignmentsValues = Get-MgBetaDeviceManagementDeviceHealthScriptAssignment -DeviceHealthScriptId $Id + $assignmentResult = @() + foreach ($assignmentEntry in $AssignmentsValues) + { + $assignmentValue = @{ + dataType = $assignmentEntry.Target.AdditionalProperties.'@odata.type' + deviceAndAppManagementAssignmentFilterType = $(if ($null -ne $assignmentEntry.Target.DeviceAndAppManagementAssignmentFilterType) + {$assignmentEntry.Target.DeviceAndAppManagementAssignmentFilterType.ToString()}) + deviceAndAppManagementAssignmentFilterId = $assignmentEntry.Target.DeviceAndAppManagementAssignmentFilterId + groupId = $assignmentEntry.Target.AdditionalProperties.groupId + } + $assignmentResult += $assignmentValue + } + $results.Add('Assignments', $assignmentResult) + + return [System.Collections.Hashtable] $results + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DetectionScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DetectionScriptParameters, + + [Parameter()] + [ValidateSet('deviceHealthScript','managedInstallerScript')] + [System.String] + $DeviceHealthScriptType, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.Boolean] + $EnforceSignatureCheck, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + $RemediationScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RemediationScriptParameters, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $RunAs32Bit, + + [Parameter()] + [ValidateSet('system','user')] + [System.String] + $RunAsAccount, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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 + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Device Remediation with DisplayName {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $CreateParameters = ([Hashtable]$BoundParameters).clone() + $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters + $CreateParameters.Add('IsGlobalScript', $false) | Out-Null + $CreateParameters.DetectionScriptContent = [System.Convert]::FromBase64String($CreateParameters.DetectionScriptContent) + $CreateParameters.RemediationScriptContent = [System.Convert]::FromBase64String($CreateParameters.RemediationScriptContent) + $CreateParameters.Remove('Id') | Out-Null + + $keys = (([Hashtable]$CreateParameters).clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.getType().Name -like '*cimInstance*') + { + $CreateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key + } + } + #region resource generator code + $CreateParameters.Add("@odata.type", "#microsoft.graph.DeviceHealthScript") + $policy = New-MgBetaDeviceManagementDeviceHealthScript -BodyParameter $CreateParameters + $assignmentsHash = @() + foreach ($assignment in $Assignments) + { + $assignmentsHash += Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignment + } + + if ($policy.id) + { + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/deviceHealthScripts' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Device Remediation with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $UpdateParameters = ([Hashtable]$BoundParameters).clone() + $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters + $UpdateParameters.DetectionScriptContent = [System.Convert]::FromBase64String($UpdateParameters.DetectionScriptContent) + $UpdateParameters.RemediationScriptContent = [System.Convert]::FromBase64String($UpdateParameters.RemediationScriptContent) + $UpdateParameters.Remove('DeviceHealthScriptType') | Out-Null + $UpdateParameters.Remove('Id') | Out-Null + + $keys = (([Hashtable]$UpdateParameters).clone()).Keys + foreach ($key in $keys) + { + if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.getType().Name -like '*cimInstance*') + { + $UpdateParameters.$key = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $UpdateParameters.$key + } + } + #region resource generator code + $UpdateParameters.Add("@odata.type", "#microsoft.graph.DeviceHealthScript") + Update-MgBetaDeviceManagementDeviceHealthScript ` + -DeviceHealthScriptId $currentInstance.Id ` + -BodyParameter $UpdateParameters + $assignmentsHash = @() + foreach ($assignment in $Assignments) + { + $assignmentsHash += Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignment + } + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/deviceHealthScripts' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Device Remediation with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementDeviceHealthScript -DeviceHealthScriptId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DetectionScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $DetectionScriptParameters, + + [Parameter()] + [ValidateSet('deviceHealthScript','managedInstallerScript')] + [System.String] + $DeviceHealthScriptType, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.Boolean] + $EnforceSignatureCheck, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + $RemediationScriptContent, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $RemediationScriptParameters, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Boolean] + $RunAs32Bit, + + [Parameter()] + [ValidateSet('system','user')] + [System.String] + $RunAsAccount, + + [Parameter(Mandatory = $true)] + [System.String] + $Id, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $Assignments, + #endregion + + [Parameter()] + [System.String] + [ValidateSet('Absent', 'Present')] + $Ensure = 'Present', + + [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 + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of the Intune Device Remediation with Id {$Id} and DisplayName {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + + if ($CurrentValues.Ensure -ne $Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + $testResult = $true + + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) + { + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') + { + $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-Not $testResult) + { + $testResult = $false + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.remove('Id') | Out-Null + $ValuesToCheck.Remove('Credential') | Out-Null + $ValuesToCheck.Remove('ApplicationId') | Out-Null + $ValuesToCheck.Remove('TenantId') | Out-Null + $ValuesToCheck.Remove('ApplicationSecret') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.String] + $Filter, + + [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 + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + #region resource generator code + # Only export scripts that are not from Microsoft + [array]$getValue = Get-MgBetaDeviceManagementDeviceHealthScript ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object -FilterScript { + $_.IsGlobalScript -eq $false + } + #endregion + + $i = 1 + $dscContent = '' + if ($getValue.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $getValue) + { + $displayedKey = $config.Id + if (-not [String]::IsNullOrEmpty($config.displayName)) + { + $displayedKey = $config.displayName + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($null -ne $Results.DetectionScriptParameters) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.DetectionScriptParameters ` + -CIMInstanceName 'MicrosoftGraphdeviceHealthScriptParameter' + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.DetectionScriptParameters = $complexTypeStringResult + } + else + { + $Results.Remove('DetectionScriptParameters') | Out-Null + } + } + if ($null -ne $Results.RemediationScriptParameters) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.RemediationScriptParameters ` + -CIMInstanceName 'MicrosoftGraphdeviceHealthScriptParameter' + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.RemediationScriptParameters = $complexTypeStringResult + } + else + { + $Results.Remove('RemediationScriptParameters') | Out-Null + } + } + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.DetectionScriptParameters) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "DetectionScriptParameters" -isCIMArray:$True + } + if ($Results.RemediationScriptParameters) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "RemediationScriptParameters" -isCIMArray:$True + } + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -isCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.schema.mof new file mode 100644 index 0000000000..8632084be7 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/MSFT_IntuneDeviceRemediation.schema.mof @@ -0,0 +1,46 @@ +[ClassVersion("1.0.0.0")] +class MSFT_DeviceManagementConfigurationPolicyAssignments +{ + [Write, Description("The type of the target assignment."), ValueMap{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}, Values{"#microsoft.graph.groupAssignmentTarget","#microsoft.graph.allLicensedUsersAssignmentTarget","#microsoft.graph.allDevicesAssignmentTarget","#microsoft.graph.exclusionGroupAssignmentTarget","#microsoft.graph.configurationManagerCollectionAssignmentTarget"}] String dataType; + [Write, Description("The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude."), ValueMap{"none","include","exclude"}, Values{"none","include","exclude"}] String deviceAndAppManagementAssignmentFilterType; + [Write, Description("The Id of the filter for the target assignment.")] String deviceAndAppManagementAssignmentFilterId; + [Write, Description("The group Id that is the target of the assignment.")] String groupId; + [Write, Description("The group Display Name that is the target of the assignment.")] String groupDisplayName; + [Write, Description("The collection Id that is the target of the assignment.(ConfigMgr)")] String collectionId; +}; +[ClassVersion("1.0.0")] +class MSFT_MicrosoftGraphDeviceHealthScriptParameter +{ + [Write, Description("Whether Apply DefaultValue When Not Assigned")] Boolean ApplyDefaultValueWhenNotAssigned; + [Write, Description("The description of the param")] String Description; + [Write, Description("Whether the param is required")] Boolean IsRequired; + [Write, Description("The name of the param")] String Name; + [Write, Description("The default value of boolean param")] Boolean DefaultValue; + [Write, Description("The type of the entity."), ValueMap{"#microsoft.graph.deviceHealthScriptBooleanParameter","#microsoft.graph.deviceHealthScriptIntegerParameter","#microsoft.graph.deviceHealthScriptStringParameter"}, Values{"#microsoft.graph.deviceHealthScriptBooleanParameter","#microsoft.graph.deviceHealthScriptIntegerParameter","#microsoft.graph.deviceHealthScriptStringParameter"}] String odataType; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneDeviceRemediation")] +class MSFT_IntuneDeviceRemediation : OMI_BaseResource +{ + [Write, Description("Description of the device health script")] String Description; + [Write, Description("The entire content of the detection powershell script")] String DetectionScriptContent; + [Write, Description("List of ComplexType DetectionScriptParameters objects."), EmbeddedInstance("MSFT_MicrosoftGraphdeviceHealthScriptParameter")] String DetectionScriptParameters[]; + [Write, Description("DeviceHealthScriptType for the script policy. Possible values are: deviceHealthScript, managedInstallerScript."), ValueMap{"deviceHealthScript","managedInstallerScript"}, Values{"deviceHealthScript","managedInstallerScript"}] String DeviceHealthScriptType; + [Required, Description("Name of the device health script")] String DisplayName; + [Write, Description("Indicate whether the script signature needs be checked")] Boolean EnforceSignatureCheck; + [Write, Description("Name of the device health script publisher")] String Publisher; + [Write, Description("The entire content of the remediation powershell script")] String RemediationScriptContent; + [Write, Description("List of ComplexType RemediationScriptParameters objects."), EmbeddedInstance("MSFT_MicrosoftGraphdeviceHealthScriptParameter")] String RemediationScriptParameters[]; + [Write, Description("List of Scope Tag IDs for the device health script")] String RoleScopeTagIds[]; + [Write, Description("Indicate whether PowerShell script(s) should run as 32-bit")] Boolean RunAs32Bit; + [Write, Description("Indicates the type of execution context. Possible values are: system, user."), ValueMap{"system","user"}, Values{"system","user"}] String RunAsAccount; + [Key, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Represents the assignment to the Intune policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; + [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Secret of the Azure Active Directory tenant used for authentication."), EmbeddedInstance("MSFT_Credential")] String ApplicationSecret; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/readme.md new file mode 100644 index 0000000000..09ed9308a5 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/readme.md @@ -0,0 +1,6 @@ + +# IntuneDeviceRemediation + +## Description + +Intune Device Remediation diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/settings.json new file mode 100644 index 0000000000..1b08179b72 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceRemediation/settings.json @@ -0,0 +1,39 @@ +{ + "resourceName": "IntuneDeviceRemediation", + "description": "This resource configures an Intune Device Remediation.", + "permissions": { + "graph": { + "application": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.Read.All" + }, + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "delegated": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.Read.All" + }, + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/1-Create.ps1 new file mode 100644 index 0000000000..47145d4c9a --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/1-Create.ps1 @@ -0,0 +1,40 @@ +<# +This example creates a new Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneDeviceRemediation 'ConfigureDeviceRemediation' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + } + ); + Credential = $Credscredential + Description = 'Description' + DetectionScriptContent = "Base64 encoded script content"; + DeviceHealthScriptType = "deviceHealthScript"; + DisplayName = "Device remediation"; + EnforceSignatureCheck = $False; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + Publisher = "Some Publisher"; + RemediationScriptContent = "Base64 encoded script content"; + RoleScopeTagIds = @("0"); + RunAs32Bit = $True; + RunAsAccount = "system"; + TenantId = $OrganizationName; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/2-Update.ps1 new file mode 100644 index 0000000000..dc4bef9bde --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/2-Update.ps1 @@ -0,0 +1,40 @@ +<# +This example updates a new Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneDeviceRemediation 'ConfigureDeviceRemediation' + { + Assignments = @( + MSFT_DeviceManagementConfigurationPolicyAssignments{ + deviceAndAppManagementAssignmentFilterType = 'none' + dataType = '#microsoft.graph.allDevicesAssignmentTarget' + } + ); + Credential = $Credscredential + Description = 'Description' + DetectionScriptContent = "Base64 encoded script content 2"; # Updated property + DeviceHealthScriptType = "deviceHealthScript"; + DisplayName = "Device remediation"; + EnforceSignatureCheck = $False; + Ensure = "Present"; + Id = '00000000-0000-0000-0000-000000000000' + Publisher = "Some Publisher"; + RemediationScriptContent = "Base64 encoded script content 2"; # Updated property + RoleScopeTagIds = @("0"); + RunAs32Bit = $True; + RunAsAccount = "system"; + TenantId = $OrganizationName; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/3-Remove.ps1 new file mode 100644 index 0000000000..85b0b6a6a0 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneDeviceRemediation/3-Remove.ps1 @@ -0,0 +1,24 @@ +<# +This example removes a Device Remediation. +#> + +Configuration Example +{ + param( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneDeviceRemediation 'ConfigureDeviceRemediation' + { + Id = '00000000-0000-0000-0000-000000000000' + DisplayName = 'Device remediation' + Ensure = 'Absent' + Credential = $Credscredential + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceRemediation.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceRemediation.Tests.ps1 new file mode 100644 index 0000000000..5b991519be --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceRemediation.Tests.ps1 @@ -0,0 +1,421 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource "IntuneDeviceRemediation" -GenericStubModule $GenericStubPath +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName Get-PSSession -MockWith { + } + + Mock -CommandName Remove-PSSession -MockWith { + } + + Mock -CommandName Update-MgBetaDeviceManagementDeviceHealthScript -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementDeviceHealthScript -MockWith { + } + + Mock -CommandName Remove-MgBetaDeviceManagementDeviceHealthScript -MockWith { + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScriptAssignment -MockWith { + } + } + # Test contexts + Context -Name "The IntuneDeviceRemediation should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DetectionScriptContent = "VGVzdA==" # "Test" + DetectionScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + Publisher = "FakeStringValue" + RemediationScriptContent = "VGVzdA==" # "Test" + RemediationScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScript -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + It 'Should Create the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-MgBetaDeviceManagementDeviceHealthScript -Exactly 1 + } + } + + Context -Name "The IntuneDeviceRemediation exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DetectionScriptContent = "VGVzdA==" # "Test" + DetectionScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + Publisher = "FakeStringValue" + RemediationScriptContent = "VGVzdA==" # "Test" + RemediationScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScript -MockWith { + return @{ + Description = "FakeStringValue" + DetectionScriptContent = [byte[]] @(84, 101, 115, 116) + DetectionScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + IsGlobalScript = $False + Publisher = "FakeStringValue" + RemediationScriptContent = [byte[]] @(84, 101, 115, 116) + RemediationScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should Remove the group from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-MgBetaDeviceManagementDeviceHealthScript -Exactly 1 + } + } + Context -Name "The IntuneDeviceRemediation Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DetectionScriptContent = "VGVzdA==" # "Test" + DetectionScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + Publisher = "FakeStringValue" + RemediationScriptContent = "VGVzdA==" # "Test" + RemediationScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScript -MockWith { + return @{ + Description = "FakeStringValue" + DetectionScriptContent = [byte[]] @(84, 101, 115, 116) + DetectionScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + IsGlobalScript = $False + Publisher = "FakeStringValue" + RemediationScriptContent = [byte[]] @(84, 101, 115, 116) + RemediationScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneDeviceRemediation exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Description = "FakeStringValue" + DetectionScriptContent = "VGVzdA==" # "Test" + DetectionScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + Publisher = "FakeStringValue" + RemediationScriptContent = "VGVzdA==" # "Test" + RemediationScriptParameters = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphdeviceHealthScriptParameter -Property @{ + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + odataType = "#microsoft.graph.deviceHealthScriptBooleanParameter" + ApplyDefaultValueWhenNotAssigned = $True + } -ClientOnly) + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScript -MockWith { + return @{ + Description = "FakeStringValue" + DetectionScriptContent = [byte[]] @(84, 101, 115, 116) + DetectionScriptParameters = @( + @{ + Name = "FakeStringValue" + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + Description = "FakeStringValue" + } + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + Id = "FakeStringValue" + IsGlobalScript = $False + Publisher = "FakeStringValue" + RemediationScriptContent = [byte[]] @(84, 101, 115, 116) + RemediationScriptParameters = @( + @{ + Name = "FakeStringValue" + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + Description = "FakeStringValue" + } + ) + RoleScopeTagIds = @("FakeStringValue") + RunAsAccount = "system" + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Update-MgBetaDeviceManagementDeviceHealthScript -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-MgBetaDeviceManagementDeviceHealthScript -MockWith { + return @{ + Description = "FakeStringValue" + DetectionScriptContent = [byte[]] @(84, 101, 115, 116) + DetectionScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + DeviceHealthScriptType = "deviceHealthScript" + DisplayName = "FakeStringValue" + EnforceSignatureCheck = $True + Id = "FakeStringValue" + IsGlobalScript = $False + Publisher = "FakeStringValue" + RemediationScriptContent = [byte[]] @(84, 101, 115, 116) + RemediationScriptParameters = @( + @{ + '@odata.type' = "#microsoft.graph.deviceHealthScriptBooleanParameter" + DefaultValue = $True + IsRequired = $True + Description = "FakeStringValue" + Name = "FakeStringValue" + ApplyDefaultValueWhenNotAssigned = $True + } + ) + RoleScopeTagIds = @("FakeStringValue") + RunAs32Bit = $True + RunAsAccount = "system" + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 27ea4bb462..3f9409e864 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -83118,3 +83118,504 @@ function Get-MgBetaDeviceManagementDeviceShellScriptAssignment #endregion +#region MgBetaDeviceManagementDeviceHealthScript +function Get-MgBetaDeviceManagementDeviceHealthScript +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $DeviceHealthScriptId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $CountVariable + ) +} + +function New-MgBetaDeviceManagementDeviceHealthScript +{ + [CmdletBinding()] + param + ( + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Assignments, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DetectionScriptContentInputFile, + + [Parameter()] + [PSObject[]] + $DetectionScriptParameters, + + [Parameter()] + [PSObject] + $DeviceHealthScriptType, + + [Parameter()] + [PSObject[]] + $DeviceRunStates, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $EnforceSignatureCheck, + + [Parameter()] + [System.String] + $HighestAvailableVersion, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsGlobalScript, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + $RemediationScriptContentInputFile, + + [Parameter()] + [PSObject[]] + $RemediationScriptParameters, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $RunAs32Bit, + + [Parameter()] + [PSObject] + $RunAsAccount, + + [Parameter()] + [PSObject] + $RunSummary, + + [Parameter()] + [System.String] + $Version, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Remove-MgBetaDeviceManagementDeviceHealthScript +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $DeviceHealthScriptId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PassThru, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Update-MgBetaDeviceManagementDeviceHealthScript +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $DeviceHealthScriptId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [PSObject] + $BodyParameter, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Collections.Hashtable] + $AdditionalProperties, + + [Parameter()] + [PSObject[]] + $Assignments, + + [Parameter()] + [System.String] + $Description, + + [Parameter()] + [System.String] + $DetectionScriptContentInputFile, + + [Parameter()] + [PSObject[]] + $DetectionScriptParameters, + + [Parameter()] + [PSObject] + $DeviceHealthScriptType, + + [Parameter()] + [PSObject[]] + $DeviceRunStates, + + [Parameter()] + [System.String] + $DisplayName, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $EnforceSignatureCheck, + + [Parameter()] + [System.String] + $HighestAvailableVersion, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IsGlobalScript, + + [Parameter()] + [System.String] + $Publisher, + + [Parameter()] + [System.String] + $RemediationScriptContentInputFile, + + [Parameter()] + [PSObject[]] + $RemediationScriptParameters, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $RunAs32Bit, + + [Parameter()] + [PSObject] + $RunAsAccount, + + [Parameter()] + [PSObject] + $RunSummary, + + [Parameter()] + [System.String] + $Version, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +#endregion + +#region MgBetaDeviceManagementDeviceHealthScriptAssignment +function Get-MgBetaDeviceManagementDeviceHealthScriptAssignment +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $DeviceHealthScriptAssignmentId, + + [Parameter()] + [System.String] + $DeviceHealthScriptId, + + [Parameter()] + [PSObject] + $InputObject, + + [Parameter()] + [System.String[]] + $ExpandProperty, + + [Parameter()] + [System.String[]] + $Property, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Search, + + [Parameter()] + [System.Int32] + $Skip, + + [Parameter()] + [System.String[]] + $Sort, + + [Parameter()] + [System.Int32] + $Top, + + [Parameter()] + [System.String] + $ResponseHeadersVariable, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Break, + + [Parameter()] + [System.Collections.IDictionary] + $Headers, + + [Parameter()] + [PSObject[]] + $HttpPipelineAppend, + + [Parameter()] + [PSObject[]] + $HttpPipelinePrepend, + + [Parameter()] + [System.Uri] + $Proxy, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ProxyCredential, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ProxyUseDefaultCredentials, + + [Parameter()] + [System.Int32] + $PageSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $All, + + [Parameter()] + [System.String] + $CountVariable + ) +} + +#endregion +