From 52c0bd630bddce07f8936e678bb13bc517bd2a78 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 17 Jul 2024 15:49:01 +0200 Subject: [PATCH 01/23] Migrate Intune Antivirus resource to new settings catalog cmdlets --- CHANGELOG.md | 7 + ...ntivirusPolicyWindows10SettingCatalog.psm1 | 767 ++++-------------- ...usPolicyWindows10SettingCatalog.schema.mof | 5 +- .../Modules/M365DSCDRGUtil.psm1 | 10 +- ...inistratorPasswordSolutionPolicy.Tests.ps1 | 7 - ...rusPolicyWindows10SettingCatalog.Tests.ps1 | 107 ++- 6 files changed, 247 insertions(+), 656 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 455cd4d420..a181bd9f8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneAntivirusPolicyWindows10SettingCatalog + * Migrate to new settings catalog cmdlets. +* M365DSCDRGUtil + * Fixes an issue where only 25 settings catalog templates were fetched with one call. + # 1.24.717.1 * AADConditionalAccessPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 index c6fd77622d..ee7e18ef29 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.psm1 @@ -165,6 +165,11 @@ function Get-TargetResource [System.String] $disablehttpparsing, + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $DisableSshParsing, + [Parameter()] [ValidateSet('0', '1')] [System.String] @@ -285,6 +290,7 @@ function Get-TargetResource $schedulescanday, [Parameter()] + [ValidateRange(0, 1380)] [System.Int32] $schedulescantime, @@ -312,6 +318,7 @@ function Get-TargetResource $signatureupdatefilesharessources, [Parameter()] + [ValidateRange(0, 24)] [System.Int32] $signatureupdateinterval, @@ -402,108 +409,76 @@ function Get-TargetResource $AccessTokens ) - Write-Verbose -Message "Checking for the Intune Endpoint Protection Policy {$DisplayName}" + try + { + Write-Verbose -Message "Checking for the Intune Endpoint Protection Policy {$DisplayName}" - $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters ` - -ErrorAction Stop + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters ` + -ErrorAction Stop - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies + #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 + #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' + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $templateReferences = "d948ff9b-99cb-4ee0-8012-1fbc09685377_1", "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", "45fea5e9-280d-4da1-9792-fb5736da0ca9_1","804339ad-1553-4478-a742-138fb5807418_1" - try - { #Retrieve policy general settings - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ExpandProperty settings -ErrorAction SilentlyContinue + $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ErrorAction SilentlyContinue if ($null -eq $policy) { - Write-Verbose -Message "No policy with Id {$Identity} was found. Trying to retrieve by name {$DisplayName}." - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -Filter "Name eq '$DisplayName'" + Write-Verbose -Message "Could not find an Intune Antivirus Policy for Windows10 Setting Catalog with Id {$Identity}" - if ($null -eq $policy) + if (-not [System.String]::IsNullOrEmpty($DisplayName)) { - Write-Verbose -Message "No policy with name {$DisplayName} was found." - return $nullResult - } - - if(([array]$policy).count -gt 1) - { - throw "A policy with a duplicated displayName {'$DisplayName'} was found - Ensure displayName is unique" + $policy = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -in $templateReferences + } } + } - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $policy.id -ExpandProperty settings -ErrorAction SilentlyContinue - + if ($null -eq $policy) + { + Write-Verbose -Message "Could not find an Intune Antivirus Policy for Windows10 Setting Catalog with Name {$DisplayName}" + return $nullResult } + $Identity = $policy.Id + Write-Verbose -Message "An Intune Antivirus Policy for Windows10 Setting Catalog with Id {$Identity} and Name {$DisplayName} was found." #Retrieve policy specific settings - $Identity = $policy.id - [array]$settings = $policy.settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Identity ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings $returnHashtable = @{} - $returnHashtable.Add('Identity', $policy.id) + $returnHashtable.Add('Identity', $Identity) $returnHashtable.Add('DisplayName', $policy.name) $returnHashtable.Add('Description', $policy.description) $returnHashtable.Add('templateId', $policy.templateReference.templateId) + $returnHashtable += $policySettings - foreach ($setting in $settings.settingInstance) - { - $addToParameters = $true - $settingName = $setting.settingDefinitionId.Split('_') | Select-Object -Last 1 - if ($settingName -eq 'options') - { - $settingName = 'tamperprotection' - } - - switch ($setting.AdditionalProperties.'@odata.type') - { - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.simpleSettingCollectionValue) - { - $values += Get-DeviceManagementConfigurationSettingInstanceValue -Setting $value - } - $settingValue = $values - } - - '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.groupSettingCollectionValue.children) - { - $settingName = $value.settingDefinitionId.split('_') | Select-Object -Last 1 - $settingValue = Get-DeviceManagementConfigurationSettingInstanceValue -Setting $value - $returnHashtable.Add($settingName, $settingValue) - $addToParameters = $false - } - } - Default - { - $settingValue = Get-DeviceManagementConfigurationSettingInstanceValue -Setting $setting.AdditionalProperties - } - } - if ($addToParameters) - { - $returnHashtable.Add($settingName, $settingValue) - } - - } $returnAssignments = @() - $graphAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $policy.Id - if ($graphAssignments.count -gt 0) + $graphAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Identity + if ($graphAssignments.Count -gt 0) { $returnAssignments += ConvertFrom-IntunePolicyAssignment ` -IncludeDeviceFilter:$true ` @@ -511,8 +486,6 @@ function Get-TargetResource } $returnHashtable.Add('Assignments', $returnAssignments) - Write-Verbose -Message "Found Endpoint Protection Policy {$($policy.name)}" - $returnHashtable.Add('Ensure', 'Present') $returnHashtable.Add('Credential', $Credential) $returnHashtable.Add('ApplicationId', $ApplicationId) @@ -703,6 +676,11 @@ function Set-TargetResource [System.String] $disablehttpparsing, + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $DisableSshParsing, + [Parameter()] [ValidateSet('0', '1')] [System.String] @@ -823,6 +801,7 @@ function Set-TargetResource $schedulescanday, [Parameter()] + [ValidateRange(0, 1380)] [System.Int32] $schedulescantime, @@ -850,6 +829,7 @@ function Set-TargetResource $signatureupdatefilesharessources, [Parameter()] + [ValidateRange(0, 24)] [System.Int32] $signatureupdateinterval, @@ -956,15 +936,7 @@ function Set-TargetResource #endregion $currentPolicy = Get-TargetResource @PSBoundParameters - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null - $PSBoundParameters.Remove('templateId') | Out-Null - $PSBoundParameters.Remove('AccessTokens') | Out-Null + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $templateReferenceId = $templateId $platforms = 'windows10' @@ -973,38 +945,41 @@ function Set-TargetResource if ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Absent') { Write-Verbose -Message "Creating new Endpoint Protection Policy {$DisplayName}" - $PSBoundParameters.Remove('DisplayName') | Out-Null - $PSBoundParameters.Remove('Description') | Out-Null - $PSBoundParameters.Remove('Identity') | Out-Null - $PSBoundParameters.Remove('Assignments') | Out-Null - - $settings = Format-M365DSCIntuneSettingCatalogPolicySettings ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` - -TemplateReferenceId $templateReferenceId - - $policy = New-IntuneDeviceConfigurationPolicy ` - -Name $DisplayName ` - -Description $Description ` - -TemplateReferenceId $templateReferenceId ` - -Platforms $platforms ` - -Technologies $technologies ` - -Settings $settings + $BoundParameters.Remove('Identity') | Out-Null + $BoundParameters.Remove('Assignments') | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReferenceId = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } - $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id -Targets $assignmentsHash + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -Assignments $Assignments -IncludeDeviceFilter:$true + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } } elseif ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Present') { Write-Verbose -Message "Updating existing Endpoint Protection Policy {$($currentPolicy.DisplayName)}" - $PSBoundParameters.Remove('DisplayName') | Out-Null - $PSBoundParameters.Remove('Description') | Out-Null - $PSBoundParameters.Remove('Identity') | Out-Null - $PSBoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('Identity') | Out-Null + $BoundParameters.Remove('Assignments') | Out-Null - $settings = Format-M365DSCIntuneSettingCatalogPolicySettings ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` - -TemplateReferenceId $templateReferenceId + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId Update-IntuneDeviceConfigurationPolicy ` -DeviceConfigurationPolicyId $currentPolicy.Identity ` @@ -1016,8 +991,10 @@ function Set-TargetResource -Settings $settings $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $currentPolicy.Identity -Targets $assignmentsHash - + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentPolicy.Identity ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' } elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') { @@ -1193,6 +1170,11 @@ function Test-TargetResource [System.String] $disablehttpparsing, + [Parameter()] + [ValidateSet('1', '0')] + [System.String] + $DisableSshParsing, + [Parameter()] [ValidateSet('0', '1')] [System.String] @@ -1313,6 +1295,7 @@ function Test-TargetResource $schedulescanday, [Parameter()] + [ValidateRange(0, 1380)] [System.Int32] $schedulescantime, @@ -1340,6 +1323,7 @@ function Test-TargetResource $signatureupdatefilesharessources, [Parameter()] + [ValidateRange(0, 24)] [System.Int32] $signatureupdateinterval, @@ -1450,9 +1434,6 @@ function Test-TargetResource throw "An error occured in Get-TargetResource, the policy {$displayName} will not be processed. Refer to the event viewer logs for more information." } - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - [Hashtable]$ValuesToCheck = @{} $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) @@ -1462,60 +1443,48 @@ function Test-TargetResource $ValuesToCheck.Add($_.Key, $null) if (-not $PSBoundParameters.ContainsKey($_.Key)) { - $value = $null - switch ($CurrentValues[$_.Key].GetType().Name) - { - 'String' - { - $value = '' - } - 'Int32' - { - $value = 0 - } - 'String[]' - { - $value = @() - } - } - $PSBoundParameters.Add($_.Key, $value) + $PSBoundParameters.Add($_.Key, $null) } } } } - $ValuesToCheck.Remove('Identity') | Out-Null - $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck - - $testResult = $true if ($CurrentValues.Ensure -ne $Ensure) { - $testResult = $false + Write-Verbose -Message "Test-TargetResource returned $false" + return $false } + $testResult = $true - #region Assignments - if ($testResult) - { - $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $PSBoundParameters.Assignments - $target = $CurrentValues.Assignments - $testResult = Compare-M365DSCIntunePolicyAssignment -Source $source -Target $target - $ValuesToCheck.Remove('Assignments') | Out-Null - } - #endregion - - if ($testResult) + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) { - foreach ($key in $PSBoundParameters.keys) + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') { - #Removing empty array when not returned from Get-Resource - $value = $PSBoundParameters.$key - if ($null -ne $value -and $value.getType().Name -like '*[[\]]' -and $value.count -eq 0 -and $null -eq $CurrentValues.$key) + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) { - $ValuesToCheck.remove($key) + break } + + $ValuesToCheck.Remove($key) | Out-Null } + } - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + $ValuesToCheck.Remove('Identity') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + if ($testResult) + { + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck $ValuesToCheck.Keys @@ -1611,16 +1580,16 @@ function Export-TargetResource Write-Host " |---[$i/$($policies.Count)] $($policy.Name)" -NoNewline $params = @{ - Identity = $policy.id + Identity = $policy.Id DisplayName = $policy.Name - TemplateId = $policy.templateReference.templateId + TemplateId = $policy.TemplateReference.TemplateId Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent + ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } @@ -1631,47 +1600,39 @@ function Export-TargetResource throw "An error occured in Get-TargetResource, the policy {$($params.displayName)} will not be processed. Refer to the event viewer logs for more information." } - if ($Results.Ensure -eq 'Present') - { - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results - if ($Results.Assignments) + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments - if ($complexTypeStringResult) - { - $Results.Assignments = $complexTypeStringResult - } - else - { - $Results.Remove('Assignments') | Out-Null - } + $Results.Assignments = $complexTypeStringResult } - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential -Verbose - - if ($Results.Assignments) + else { - $isCIMArray = $false - if ($Results.Assignments.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + $Results.Remove('Assignments') | Out-Null } + } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential -Verbose - Write-Host $Global:M365DSCEmojiGreenCheckMark - $i++ + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + + Write-Host $Global:M365DSCEmojiGreenCheckMark + $i++ } return $dscContent } @@ -1697,420 +1658,4 @@ function Export-TargetResource } } -function Get-DeviceManagementConfigurationSettingInstanceValue -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $Setting - ) - #write-verbose -Message ($setting|fl|out-string) - #write-verbose -Message ("setting: "+$setting.settingDefinitionId+" type: "+$setting.'@odata.type') - switch ($setting.'@odata.type') - { - '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - { - $settingValue = $setting.choiceSettingValue.value.split('_') | Select-Object -Last 1 - - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' - { - $settingValue = $setting.simpleSettingValue.value - } - Default - { - $settingValue = $setting.value - } - } - return $settingValue -} - -function New-IntuneDeviceConfigurationPolicy -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param ( - - [Parameter(Mandatory = 'true')] - [System.String] - $Name, - - [Parameter()] - [System.String] - $Description, - - [Parameter()] - [System.String] - $Platforms, - - [Parameter()] - [System.String] - $Technologies, - - [Parameter()] - [System.String] - $TemplateReferenceId, - - [Parameter()] - [Array] - $Settings - - ) - try - { - $Uri = 'https://graph.microsoft.com/beta/deviceManagement/configurationPolicies' - - $policy = @{ - 'name' = $Name - 'description' = $Description - 'platforms' = $Platforms - 'technologies' = $Technologies - 'templateReference' = @{'templateId' = $TemplateReferenceId } - 'settings' = $Settings - } - $body = $policy | ConvertTo-Json -Depth 20 - #Write-Verbose -Message $body - Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $body -ErrorAction Stop - - } - catch - { - New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - #write-verbose ($_ | out-string) - return $null - } -} -function Update-IntuneDeviceConfigurationPolicy -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param ( - [Parameter(Mandatory = 'true')] - [System.String] - $DeviceConfigurationPolicyId, - - [Parameter()] - [System.String] - $Name, - - [Parameter()] - [System.String] - $Description, - - [Parameter()] - [System.String] - $Platforms, - - [Parameter()] - [System.String] - $Technologies, - - [Parameter()] - [System.String] - $TemplateReferenceId, - - [Parameter()] - [Array] - $Settings - - ) - try - { - $Uri = "https://graph.microsoft.com/beta/deviceManagement/configurationPolicies/$DeviceConfigurationPolicyId" - - $policy = @{ - 'name' = $Name - 'description' = $Description - 'platforms' = $Platforms - 'templateReference' = @{'templateId' = $TemplateReferenceId } - 'technologies' = $Technologies - 'settings' = $Settings - } - $body = $policy | ConvertTo-Json -Depth 20 - #write-verbose -Message $body - Invoke-MgGraphRequest -Method PUT -Uri $Uri -Body $body -ErrorAction Stop 4> $null - - } - catch - { - New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - - return $null - } -} - -function Format-M365DSCParamsToSettingInstance -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - - [Parameter()] - $TemplateSetting, - - [Parameter()] - [System.Boolean] - $IncludeSettingInstanceTemplateId = $true, - - [Parameter()] - [System.Boolean] - $IncludeSettingValueTemplateId = $true - - ) - - $DSCParams.Remove('Verbose') | Out-Null - $results = @() - - foreach ($param in $DSCParams.Keys) - { - $settingInstance = [ordered]@{} - $settingInstance.add('settingDefinitionId', $templateSetting.settingDefinitionId) - if ($IncludeSettingInstanceTemplateId -and -Not [string]::IsNullOrEmpty($templateSetting.settingInstanceTemplateId)) - { - $settingInstance.add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $templateSetting.settingInstanceTemplateId }) - } - - $odataType = $templateSetting.AdditionalProperties.'@odata.type' - if ([string]::IsNullOrEmpty($odataType)) - { - $odataType = $templateSetting.'@odata.type' - } - $settingInstance.add('@odata.type', $odataType.replace('Template', '')) - - switch ($odataType) - { - '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstanceTemplate' - { - $choiceSettingValue = [ordered]@{} - $choiceSettingValue.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationChoiceSettingValue') - $choiceSettingValue.add('children', @()) - $settingValueTemplateId = $templateSetting.AdditionalProperties.choiceSettingValueTemplate.settingValueTemplateId - if ($IncludeSettingValueTemplateId -and -Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $choiceSettingValue.add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) - } - $choiceSettingValue.add('value', "$($templateSetting.settingDefinitionId)`_$($DSCParams.$param)") - $settingInstance.add('choiceSettingValue', $choiceSettingValue) - $results += $settingInstance - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstanceTemplate' - { - $simpleSettingCollectionValues = @() - - foreach ($value in $DSCParams.$param) - { - $simpleSettingCollectionValue = @{} - $settingValueTemplateId = $templateSetting.AdditionalProperties.simpleSettingCollectionValueTemplate.settingValueTemplateId - if ($IncludeSettingValueTemplateId -and -Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $simpleSettingCollectionValue.add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) - } - $settingValueDataType = $templateSetting.AdditionalProperties.simpleSettingCollectionValueTemplate.'@odata.type'.replace('Template', '') - $simpleSettingCollectionValue.add('@odata.type', $settingValueDataType) - $simpleSettingCollectionValue.add('value', $value) - $simpleSettingCollectionValues += $simpleSettingCollectionValue - } - $settingInstance.add('simpleSettingCollectionValue', $simpleSettingCollectionValues) - - $results += $settingInstance - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstanceTemplate' - { - $simpleSettingValue = @{} - $SettingValueType = $templateSetting.AdditionalProperties.simpleSettingValueTemplate.'@odata.type' - if (-Not [string]::IsNullOrEmpty($SettingValueType)) - { - $simpleSettingValue.add('@odata.type', $SettingValueType.replace('Template', '')) - } - $simpleSettingValue.add('value', $DSCParams.$param) - - $settingValueTemplateId = $templateSetting.AdditionalProperties.simpleSettingValueTemplate.settingValueTemplateId - if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $simpleSettingValue.add('settingValueTemplateReference', @{'settingValueTemplateId' = $settingValueTemplateId }) - } - - $settingInstance.add('simpleSettingValue', $simpleSettingValue) - $results += $settingInstance - } - } - } - - if ($results.count -eq 1) - { - return $results[0] - } - return $results -} - -function Format-M365DSCIntuneSettingCatalogPolicySettings -{ - [CmdletBinding()] - [OutputType([System.Array])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - - [Parameter(Mandatory = 'true')] - [System.String] - $templateReferenceId - ) - - $DSCParams.Remove('Identity') | Out-Null - $DSCParams.Remove('DisplayName') | Out-Null - $DSCParams.Remove('Description') | Out-Null - - $settings = @() - - $templateSettings = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -DeviceManagementConfigurationPolicyTemplateId $templateReferenceId -All - - #write-verbose -Message ( $DSCParams|out-string) - - $simpleSettings = @() - $simpleSettings += $templateSettings.SettingInstanceTemplate | Where-Object -FilterScript ` - { $_.AdditionalProperties.'@odata.type' -ne '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate' } - - $keys = $DSCParams.keys - $keys = $keys -replace 'tamperprotection', 'options' - foreach ($templateSetting in $simpleSettings) - { - $setting = @{} - $settingKey = $keys | Where-Object -FilterScript { $templateSetting.settingDefinitionId -like "*$($_)" } - $originalKey = $settingKey - if ($settingKey -eq 'options') - { - $originalKey = 'tamperprotection' - } - if ((-not [String]::IsNullOrEmpty($settingKey)) -and $null -ne $DSCParams."$originalKey") - { - $setting.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') - - $includeValueReference = $true - $includeSettingInstanceReference = $true - $doNotIncludesettingInstanceReferenceKeys = @( - 'highseveritythreats' - 'lowseveritythreats' - ) - $noValueReferenceKeys = @( - 'excludedpaths' - 'excludedprocesses' - 'excludedextensions' - ) - if ($originalKey -in $noValueReferenceKeys) - { - $includeValueReference = $false - } - if ($originalKey -in $doNotIncludesettingInstanceReferenceKeys) - { - $includeSettingInstanceReference = $false - } - $myFormattedSetting = Format-M365DSCParamsToSettingInstance -DSCParams @{$settingKey = $DSCParams."$originalKey" } ` - -TemplateSetting $templateSetting ` - -IncludeSettingValueTemplateId $includeValueReference ` - -IncludeSettingInstanceTemplateId $includeSettingInstanceReference - - $setting.add('settingInstance', $myFormattedSetting) - $settings += $setting - $DSCParams.Remove($settingKey) | Out-Null - - } - } - - $groupCollectionTemplateSettings = @() - $groupCollectionTemplateSettings += $templateSettings.SettingInstanceTemplate | Where-Object -FilterScript ` - { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate' } - - foreach ($groupCollectionTemplateSetting in $groupCollectionTemplateSettings) - { - $setting = @{} - $setting.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationSetting') - $settingInstance = [ordered]@{} - $settingInstance.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance') - $settingInstance.add('settingDefinitionId', $groupCollectionTemplateSetting.settingDefinitionId) - $settingInstance.add('settingInstanceTemplateReference', @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstanceTemplateReference' - 'settingInstanceTemplateId' = $groupCollectionTemplateSetting.settingInstanceTemplateId - }) - $groupSettingCollectionValues = @() - $groupSettingCollectionValueChildren = @() - $groupSettingCollectionValue = @{} - $groupSettingCollectionValue.add('@odata.type', '#microsoft.graph.deviceManagementConfigurationGroupSettingValue') - - $settingValueTemplateId = $groupCollectionTemplateSetting.AdditionalProperties.groupSettingCollectionValueTemplate.settingValueTemplateId - if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $groupSettingCollectionValue.add('settingValueTemplateReference', @{'settingValueTemplateId' = $SettingValueTemplateId }) - } - - foreach ($key in $DSCParams.keys) - { - $templateValue = $groupCollectionTemplateSetting.AdditionalProperties.groupSettingCollectionValueTemplate.children | Where-Object ` - -FilterScript { $_.settingDefinitionId -like "*$key" } - if ($templateValue) - { - $includeValueReference = $true - $includeSettingInstanceReference = $true - $doNotIncludesettingInstanceReferenceKeys = @( - 'highseveritythreats' - 'lowseveritythreats' - 'moderateseveritythreats' - 'severethreats' - ) - $noValueReferenceKeys = @( - 'excludedpaths' - 'excludedprocesses' - 'excludedextensions' - 'highseveritythreats' - 'lowseveritythreats' - 'moderateseveritythreats' - 'severethreats' - ) - if ($key -in $noValueReferenceKeys) - { - $includeValueReference = $false - } - if ($key -in $doNotIncludesettingInstanceReferenceKeys) - { - $includeSettingInstanceReference = $false - } - $groupSettingCollectionValueChild = Format-M365DSCParamsToSettingInstance ` - -DSCParams @{$key = $DSCParams."$key" } ` - -TemplateSetting $templateValue ` - -IncludeSettingValueTemplateId $includeValueReference ` - -IncludeSettingInstanceTemplateId $includeSettingInstanceReference - - $groupSettingCollectionValueChildren += $groupSettingCollectionValueChild - } - } - - $groupSettingCollectionValue.add('children', $groupSettingCollectionValueChildren) - $groupSettingCollectionValues += $groupSettingCollectionValue - $settingInstance.add('groupSettingCollectionValue', $groupSettingCollectionValues) - - $setting.add('settingInstance', $settingInstance) - - if ($setting.settingInstance.groupSettingCollectionValue.children.count -gt 0) - { - $settings += $setting - } - } - - return $settings -} - Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof index 01e5b4d249..f88d71bef5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof @@ -59,6 +59,7 @@ class MSFT_IntuneAntivirusPolicyWindows10SettingCatalog : OMI_BaseResource [Write, Description("This policy setting allows you to configure catch-up scans for scheduled quick scans. (1: disabled, 0: enabled)"), ValueMap{"0","1"}, Values{"0","1"}] String disablecatchupquickscan; [Write, Description("Disables or enables DNS over TCP Parsing for Network Protection. (0: enable feature. 1: disable feature)"), ValueMap{"0","1"}, Values{"0","1"}] String disablednsovertcpparsing; [Write, Description("Disables or enables HTTP Parsing for Network Protection. (0: enable feature. 1: disable feature)"), ValueMap{"0","1"}, Values{"0","1"}] String disablehttpparsing; + [Write, Description("Disable Ssh Parsing (1: SSH parsing is disabled, 0: SSH parsing is enabled)"), ValueMap{"1", "0"}, Values{"1", "0"}] String DisableSshParsing; [Write, Description("This policy setting allows you to enable or disable low CPU priority for scheduled scans. (0: disable feature. 1: enable feature)"), ValueMap{"0","1"}, Values{"0","1"}] String enablelowcpupriority; [Write, Description("This policy allows you to turn on network protection (block/audit) or off. (0: disabled, 1: block mode, 2: audit mode)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String enablenetworkprotection; [Write, Description("Allows an administrator to specify a list of file type extensions to ignore during a scan.")] String excludedextensions[]; @@ -73,13 +74,13 @@ class MSFT_IntuneAntivirusPolicyWindows10SettingCatalog : OMI_BaseResource [Write, Description("Selects whether to perform a quick scan or full scan. (1: Quick scan, 2: Full scan)"), ValueMap{"1","2"}, Values{"1","2"}] String scanparameter; [Write, Description("Selects the time of day that the Windows Defender quick scan should run.")] sInt32 schedulequickscantime; [Write, Description("Selects the day that the Windows Defender scan should run. (0: Every day, 1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday, 7: Saturday, 8: No scheduled scan)"), ValueMap{"0","1","2","3","4","5","6","7","8"}, Values{"0","1","2","3","4","5","6","7","8"}] String schedulescanday; - [Write, Description("Selects the time of day that the Windows Defender scan should run.")] sInt32 schedulescantime; + [Write, Description("Selects the time of day that the Windows Defender scan should run. Must be between 0 and 1380 minutes.")] sInt32 schedulescantime; [Write, Description("This setting disables TLS Parsing for Network Protection. (0: enabled, 1: disabled)"), ValueMap{"0","1"}, Values{"0","1"}] String disabletlsparsing; [Write, Description("Specifies if the start time of the scan is randomized. (0: no randomization, 1: randomized)"), ValueMap{"0","1"}, Values{"0","1"}] String randomizescheduletasktimes; [Write, Description("This setting allows you to configure the scheduler randomization in hours. The randomization interval is [1 - 23] hours.")] sInt32 schedulerrandomizationtime; [Write, Description("This policy setting allows you to define the order in which different definition update sources should be contacted.")] String signatureupdatefallbackorder[]; [Write, Description("This policy setting allows you to configure UNC file share sources for downloading definition updates.")] String signatureupdatefilesharessources[]; - [Write, Description("Specifies the interval (in hours) that will be used to check for signatures, so instead of using the ScheduleDay and ScheduleTime the check for new signatures will be set according to the interval.")] sInt32 signatureupdateinterval; + [Write, Description("Specifies the interval (in hours) that will be used to check for signatures, so instead of using the ScheduleDay and ScheduleTime the check for new signatures will be set according to the interval. Must be between 0 and 24 hours.")] sInt32 signatureupdateinterval; [Write, Description("Checks for the user consent level in Windows Defender to send data. (0: Always prompt, 1: Send safe samples automatically, 2: Never send, 3: Send all samples automatically)"), ValueMap{"0","1","2","3"}, Values{"0","1","2","3"}] String submitsamplesconsent; [Write, Description("This policy setting controls whether or not complex list settings configured by a local administrator are merged with managed settings. (0: enable local admin merge, 1: disable local admin merge)"), ValueMap{"0","1"}, Values{"0","1"}] String disablelocaladminmerge; [Write, Description("Allows or disallows Windows Defender On Access Protection functionality. (0: disable feature. 1: enable feature)"), ValueMap{"0","1"}, Values{"0","1"}] String allowonaccessprotection; diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 8098a13922..6f84482e14 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1512,7 +1512,10 @@ function Get-IntuneSettingCatalogPolicySetting $DSCParams.Remove('Description') | Out-Null # Prepare setting definitions mapping - $settingTemplates = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -DeviceManagementConfigurationPolicyTemplateId $TemplateId -ExpandProperty 'SettingDefinitions' + $settingTemplates = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate ` + -DeviceManagementConfigurationPolicyTemplateId $TemplateId ` + -ExpandProperty 'SettingDefinitions' ` + -All $settingInstances = @() # Iterate over all setting instance templates @@ -1560,6 +1563,11 @@ function Get-IntuneSettingCatalogPolicySetting if ($settingValue.Count -gt 0) { + if ($settingValue.Keys -contains 'groupSettingCollectionValue' -and $settingValue.groupSettingCollectionValue.children.Count -eq 0) + { + continue + } + $settingInstance += [Hashtable]$settingValue if ($settingInstance.Keys -notcontains 'settingDefinitionId') { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionLocalAdministratorPasswordSolutionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionLocalAdministratorPasswordSolutionPolicy.Tests.ps1 index a00146b23b..791f56e8c4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionLocalAdministratorPasswordSolutionPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAccountProtectionLocalAdministratorPasswordSolutionPolicy.Tests.ps1 @@ -57,13 +57,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return ,@() } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { - return @(@{ - dataType = '#microsoft.graph.exclusionGroupAssignmentTarget' - collectionId = '26d60dd1-fab6-47bf-8656-358194c1a49d' - }) - } - Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyWindows10SettingCatalog.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyWindows10SettingCatalog.Tests.ps1 index 53ddcb6aeb..c1ab851ec4 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyWindows10SettingCatalog.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyWindows10SettingCatalog.Tests.ps1 @@ -34,7 +34,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { } - Mock -CommandName New-IntuneDeviceConfigurationPolicy -MockWith { + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { return @{ Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' } @@ -42,9 +42,39 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplate -MockWith { + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { return @{ - TemplateId = 'd02f2162-fcac-48db-9b7b-b0a3f160d2c2_1' + Id = 0 + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_defender_allowarchivescanning' + Name = 'AllowArchiveScanning' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' + AdditionalProperties = $null + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_1' + settingValueTemplateReference = @{ + settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' + useTemplateDefault = $false + } + children = @() + } + } + } } } @@ -57,35 +87,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { TemplateId = 'd948ff9b-99cb-4ee0-8012-1fbc09685377_1' TemplateFamily = 'endpointSecurityAntivirus' } - Settings = @(@{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' - AdditionalProperties = $null - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - choiceSettingValue = @{ - value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_0' #drift - settingValueTemplateReference = @{ - settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' - useTemplateDefault = $false - } - children = $null - } - } - - } - AdditionalProperties = $null - }) } } Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { - return @(@{ + return @( + @{ Id = '12345-12345-12345-12345-12345' Source = 'direct' SourceId = '12345-12345-12345-12345-12345' @@ -99,7 +106,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } ) } - }) + } + ) } Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { @@ -121,7 +129,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' DeviceAndAppManagementAssignmentFilterType = 'none' - DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' GroupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' } -ClientOnly) ) @@ -148,7 +155,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should create the instance from the Set method' { Set-TargetResource @testParams - Should -Invoke -CommandName New-IntuneDeviceConfigurationPolicy -Exactly 1 + Should -Invoke -CommandName New-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 } } @@ -160,7 +167,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' DeviceAndAppManagementAssignmentFilterType = 'none' - DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' GroupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' } -ClientOnly) ) @@ -171,6 +177,39 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { templateId = 'd948ff9b-99cb-4ee0-8012-1fbc09685377_1' Identity = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_defender_allowarchivescanning' + Name = 'AllowArchiveScanning' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_defender_allowarchivescanning' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '7c5c9cde-f74d-4d11-904f-de4c27f72d89' + AdditionalProperties = $null + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + value = 'device_vendor_msft_policy_config_defender_allowarchivescanning_0' #drift + settingValueTemplateReference = @{ + settingValueTemplateId = '9ead75d4-6f30-4bc5-8cc5-ab0f999d79f0' + useTemplateDefault = $false + } + children = $null + } + } + } + } + } } It 'Should return Present from the Get method' { @@ -190,12 +229,11 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Context -Name 'When the instance already exists and IS in the Desired State' -Fixture { BeforeAll { $testParams = @{ - allowarchivescanning = '0' + allowarchivescanning = '1' Assignments = [CimInstance[]]@( (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' DeviceAndAppManagementAssignmentFilterType = 'none' - DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' GroupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' } -ClientOnly) ) @@ -221,7 +259,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' DeviceAndAppManagementAssignmentFilterType = 'none' - DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' GroupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' } -ClientOnly) ) From ccf8a61d8e87a54a91bcbeb715140a8b76dc697d Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Thu, 18 Jul 2024 15:04:59 +0200 Subject: [PATCH 02/23] Add template display name to template id for Intune Antivirus resource --- ...MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof index f88d71bef5..f95e692cab 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog/MSFT_IntuneAntivirusPolicyWindows10SettingCatalog.schema.mof @@ -88,7 +88,7 @@ class MSFT_IntuneAntivirusPolicyWindows10SettingCatalog : OMI_BaseResource [Write, Description("Allows an administrator to specify moderate severity threats corresponding action ID to take."),ValueMap{"clean", "quarantine","remove", "allow", "userdefined","block"}, Values{"clean", "quarantine","remove", "allow", "userdefined","block"}] String moderateseveritythreats; [Write, Description("Allows an administrator to specify high severity threats corresponding action ID to take."),ValueMap{"clean", "quarantine","remove", "allow", "userdefined","block"}, Values{"clean", "quarantine","remove", "allow", "userdefined","block"}] String severethreats; [Write, Description("Allows an administrator to specify severe threats corresponding action ID to take."),ValueMap{"clean", "quarantine","remove", "allow", "userdefined","block"}, Values{"clean", "quarantine","remove", "allow", "userdefined","block"}] String highseveritythreats; - [Write, Description("Template Id of the policy."),ValueMap{"d948ff9b-99cb-4ee0-8012-1fbc09685377_1", "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", "45fea5e9-280d-4da1-9792-fb5736da0ca9_1","804339ad-1553-4478-a742-138fb5807418_1"}, Values{"d948ff9b-99cb-4ee0-8012-1fbc09685377_1", "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", "45fea5e9-280d-4da1-9792-fb5736da0ca9_1","804339ad-1553-4478-a742-138fb5807418_1"}] String templateId; + [Write, Description("Template Id of the policy. 0: Windows Security Experience, 1: Defender Update controls, 2: Microsoft Defender Antivirus exclusions, 3: Microsoft Defender Antivirus"),ValueMap{"d948ff9b-99cb-4ee0-8012-1fbc09685377_1", "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", "45fea5e9-280d-4da1-9792-fb5736da0ca9_1","804339ad-1553-4478-a742-138fb5807418_1"}, Values{"d948ff9b-99cb-4ee0-8012-1fbc09685377_1", "e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1", "45fea5e9-280d-4da1-9792-fb5736da0ca9_1","804339ad-1553-4478-a742-138fb5807418_1"}] String templateId; [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 Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From 9754c43ca8f96a6f2b0ae0a88c849fc70d27d78d Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Thu, 18 Jul 2024 13:16:37 +0200 Subject: [PATCH 03/23] Migrate Intune ASR resource to new settings catalog cmdlets --- CHANGELOG.md | 6 + ...tionRulesPolicyWindows10ConfigManager.psm1 | 489 +++++------------- ...lesPolicyWindows10ConfigManager.schema.mof | 2 +- ...ulesPolicyWindows10ConfigManager.Tests.ps1 | 159 ++---- 4 files changed, 176 insertions(+), 480 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 455cd4d420..74310e3917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager + * Migrate to new settings catalog cmdlets. + FIXES [#3966](https://github.com/microsoft/Microsoft365DSC/issues/3966) + # 1.24.717.1 * AADConditionalAccessPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.psm1 index fbd8315666..c00be32dd2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.psm1 @@ -114,7 +114,7 @@ function Get-TargetResource $ControlledFolderAccessAllowedApplications, [Parameter()] - [ValidateSet('0', '1', '2')] + [ValidateSet('0', '1', '2', '3', '4')] [System.String] $EnableControlledFolderAccess, @@ -156,106 +156,67 @@ function Get-TargetResource $AccessTokens ) - Write-Verbose -Message "Checking for the Intune Endpoint Protection Policy {$DisplayName}" + try + { - $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` - -InboundParameters $PSBoundParameters ` - -ErrorAction Stop + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters ` + -ErrorAction Stop - #Ensure the proper dependencies are installed in the current environment. - Confirm-M365DSCDependencies + #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 + #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' + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + + $templateReferenceId = '5dd36540-eb22-4e7e-b19c-2a07772ba627_1' + # Retrieve policy general settings + $policy = $null + $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ErrorAction SilentlyContinue - try - { - #Retrieve policy general settings - if (-not [System.String]::IsNullOrEmpty($Identity)) - { - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ErrorAction Stop - } if ($null -eq $policy) { - Write-Verbose -Message "No Endpoint Protection Policy {id: '$Identity'} was found" - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -Filter "name eq '$DisplayName'" -ErrorAction SilentlyContinue + Write-Verbose -Message "No Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager with Id {$Identity} was found" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $policy = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName' and templateReference/TemplateId eq '$templateReferenceId'" ` + -ErrorAction SilentlyContinue + } + if ($null -eq $policy) { - Write-Verbose -Message "No Endpoint Protection Policy {displayName: '$DisplayName'} was found" + Write-Verbose -Message "No Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager with Name {$DisplayName} was found" return $nullResult } } $Identity = $policy.Id - Write-Verbose -Message "Found Endpoint Protection Policy {$($policy.id):$($policy.Name)}" + Write-Verbose -Message "Found Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager with Id {$($Identity) and Name $($policy.Name)}" - #Retrieve policy specific settings + # Retrieve policy specific settings [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` -DeviceManagementConfigurationPolicyId $Identity ` + -ExpandProperty 'settingDefinitions' ` -ErrorAction Stop $returnHashtable = @{} $returnHashtable.Add('Identity', $Identity) - $returnHashtable.Add('DisplayName', $policy.name) - $returnHashtable.Add('Description', $policy.description) - - foreach ($setting in $settings.settingInstance) - { - $addToParameters = $true - $settingName = $setting.settingDefinitionId.Split('_') | Select-Object -Last 1 - - switch ($setting.AdditionalProperties.'@odata.type') - { - - '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' - { - $settingValue = $setting.AdditionalProperties.simpleSettingValue.value - } - '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' - { - $settingValue = $setting.AdditionalProperties.choiceSettingValue.value.split('_') | Select-Object -Last 1 - } - '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.groupSettingCollectionValue.children) - { - $settingName = $value.settingDefinitionId.split('_') | Select-Object -Last 1 - $settingValue = $value.choiceSettingValue.value.split('_') | Select-Object -Last 1 - $returnHashtable.Add($settingName, $settingValue) - $addToParameters = $false - } - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' - { - $values = @() - foreach ($value in $setting.AdditionalProperties.simpleSettingCollectionValue.value) - { - $values += $value - } - $settingValue = $values - } - Default - { - $settingValue = $setting.value - } - } + $returnHashtable.Add('DisplayName', $policy.Name) + $returnHashtable.Add('Description', $policy.Description) - if ($addToParameters) - { - $returnHashtable.Add($settingName, $settingValue) - } - } + $returnHashtable = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $returnHashtable $returnAssignments = @() $graphAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Identity @@ -407,7 +368,7 @@ function Set-TargetResource $ControlledFolderAccessAllowedApplications, [Parameter()] - [ValidateSet('0', '1', '2')] + [ValidateSet('0', '1', '2', '3', '4')] [System.String] $EnableControlledFolderAccess, @@ -462,14 +423,7 @@ function Set-TargetResource #endregion $currentPolicy = Get-TargetResource @PSBoundParameters - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null - $PSBoundParameters.Remove('AccessTokens') | Out-Null + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $templateReferenceId = '5dd36540-eb22-4e7e-b19c-2a07772ba627_1' $platforms = 'windows10' @@ -477,10 +431,12 @@ function Set-TargetResource if ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Absent') { - Write-Verbose -Message "Creating new Endpoint Protection Policy {$DisplayName}" + Write-Verbose -Message "Creating new Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager {$DisplayName}" + $BoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('Identity') | Out-Null $settings = Get-IntuneSettingCatalogPolicySetting ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` -TemplateId $templateReferenceId $createParameters = @{ @@ -491,21 +447,26 @@ function Set-TargetResource Technologies = $technologies Settings = $settings } - New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters - - $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments - Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $Identity ` - -Targets $assignmentsHash + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } } elseif ($Ensure -eq 'Present' -and $currentPolicy.Ensure -eq 'Present') { - Write-Verbose -Message "Updating existing Endpoint Protection Policy {$($currentPolicy.DisplayName)}" + Write-Verbose -Message "Updating existing Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager {$($currentPolicy.DisplayName)}" + $BoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('Identity') | Out-Null #format settings from PSBoundParameters for update $settings = Get-IntuneSettingCatalogPolicySetting ` - -DSCParams ([System.Collections.Hashtable]$PSBoundParameters) ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` -TemplateId $templateReferenceId Update-IntuneDeviceConfigurationPolicy ` @@ -521,13 +482,14 @@ function Set-TargetResource $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments Update-DeviceConfigurationPolicyAssignment ` -DeviceConfigurationPolicyId $currentPolicy.Identity ` - -Targets $assignmentsHash + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' #endregion } elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') { - Write-Verbose -Message "Removing Endpoint Protection Policy {$($currentPolicy.DisplayName)}" - Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity + Write-Verbose -Message "Removing Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager {$($currentPolicy.DisplayName)}" + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentPolicy.Identity } } @@ -647,7 +609,7 @@ function Test-TargetResource $ControlledFolderAccessAllowedApplications, [Parameter()] - [ValidateSet('0', '1', '2')] + [ValidateSet('0', '1', '2', '3', '4')] [System.String] $EnableControlledFolderAccess, @@ -700,78 +662,68 @@ function Test-TargetResource -Parameters $PSBoundParameters Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Endpoint Protection Policy {$DisplayName}" + Write-Verbose -Message "Testing configuration of Intune Attack Surface Reduction Rules Policy for Windows10 Config Manager {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - - $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Identity') | Out-Null - - $testResult = $true - if ([Array]$Assignments.count -ne $CurrentValues.Assignments.count) - { - Write-Verbose -Message "Configuration drift:Number of assignments does not match: Source=$([Array]$Assignments.count) Target=$($CurrentValues.Assignments.count)" - $testResult = $false - } - if ($testResult) - { - foreach ($assignment in $CurrentValues.Assignments) + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) { - if ($null -ne $Assignment) + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) { - #GroupId Assignment - if (-not [String]::IsNullOrEmpty($assignment.groupId)) - { - $source = [Array]$ValuesToCheck.Assignments | Where-Object -FilterScript { $_.groupId -eq $assignment.groupId } - if (-not $source) - { - Write-Verbose -Message "Configuration drift: groupId {$($assignment.groupId)} not found" - $testResult = $false - break - } - $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment - } - #AllDevices/AllUsers assignment - else + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) { - $source = [Array]$ValuesToCheck.Assignments | Where-Object -FilterScript { $_.dataType -eq $assignment.dataType } - if (-not $source) - { - Write-Verbose -Message "Configuration drift: {$($assignment.dataType)} not found" - $testResult = $false - break - } - $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment + $PSBoundParameters.Add($_.Key, $null) } } + } + } + + 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 ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) if (-not $testResult) { - $testResult = $false break } + $ValuesToCheck.Remove($key) | Out-Null } - } - $ValuesToCheck.Remove('Assignments') | Out-Null + + $ValuesToCheck.Remove('Identity') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" if ($testResult) { - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` -ValuesToCheck $ValuesToCheck.Keys } - Write-Verbose -Message "Test-TargetResource returned $TestResult" + Write-Verbose -Message "Test-TargetResource returned $testResult" - return $TestResult + return $testResult } function Export-TargetResource @@ -868,48 +820,39 @@ function Export-TargetResource } $Results = Get-TargetResource @params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results - if ($Results.Ensure -eq 'Present') + if ($Results.Assignments) { - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - - if ($Results.Assignments) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) { - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject ([Array]$Results.Assignments) -CIMInstanceName DeviceManagementConfigurationPolicyAssignments - if ($complexTypeStringResult) - { - $Results.Assignments = $complexTypeStringResult - } - else - { - $Results.Remove('Assignments') | Out-Null - } + $Results.Assignments = $complexTypeStringResult } - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - - if ($Results.Assignments) + else { - $isCIMArray = $false - if ($Results.Assignments.getType().Fullname -like '*[[\]]') - { - $isCIMArray = $true - } - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$isCIMArray + $Results.Remove('Assignments') | Out-Null } + } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential - Write-Host $Global:M365DSCEmojiGreenCheckMark - $i++ + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Assignments' -IsCIMArray:$true } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + + Write-Host $Global:M365DSCEmojiGreenCheckMark + $i++ } return $dscContent } @@ -935,187 +878,5 @@ function Export-TargetResource return '' } } -function Get-IntuneSettingCatalogPolicySetting -{ - [CmdletBinding()] - [OutputType([System.Array])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - [Parameter(Mandatory = 'true')] - [System.String] - $TemplateId - ) - - $DSCParams.Remove('Identity') | Out-Null - $DSCParams.Remove('DisplayName') | Out-Null - $DSCParams.Remove('Description') | Out-Null - - #Prepare setting definitions mapping - $settingDefinitions = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -DeviceManagementConfigurationPolicyTemplateId $TemplateId - $settingInstances = @() - foreach ($settingDefinition in $settingDefinitions.SettingInstanceTemplate) - { - - $settingInstance = @{} - $settingName = $settingDefinition.SettingDefinitionId.split('_') | Select-Object -Last 1 - $settingType = $settingDefinition.AdditionalProperties.'@odata.type'.replace('InstanceTemplate', 'Instance') - $settingInstance.Add('settingDefinitionId', $settingDefinition.settingDefinitionId) - $settingInstance.Add('@odata.type', $settingType) - if (-Not [string]::IsNullOrEmpty($settingDefinition.settingInstanceTemplateId)) - { - $settingInstance.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $settingDefinition.settingInstanceTemplateId }) - } - $settingValueName = $settingType.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $settingValueName = $settingValueName.Substring(0, 1).ToLower() + $settingValueName.Substring(1, $settingValueName.length - 1 ) - $settingValueType = $settingDefinition.AdditionalProperties."$($settingValueName)Template".'@odata.type' - if ($null -ne $settingValueType) - { - $settingValueType = $settingValueType.replace('ValueTemplate', 'Value') - } - $settingValueTemplateId = $settingDefinition.AdditionalProperties."$($settingValueName)Template".settingValueTemplateId - $settingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` - -DSCParams $DSCParams ` - -SettingDefinition $settingDefinition ` - -SettingName $settingName ` - -SettingType $settingType ` - -SettingValueName $settingValueName ` - -SettingValueType $settingValueType ` - -SettingValueTemplateId $settingValueTemplateId - if ($null -ne $settingValue) - { - $settingInstance += [Hashtable]$settingValue - } - - $settingInstances += @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSetting' - 'settingInstance' = $settingInstance - } - } - - return $settingInstances -} -function Get-IntuneSettingCatalogPolicySettingInstanceValue -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] - param( - [Parameter(Mandatory = 'true')] - [System.Collections.Hashtable] - $DSCParams, - - [Parameter()] - $SettingDefinition, - - [Parameter()] - [System.String] - $SettingType, - - [Parameter()] - [System.String] - $SettingName, - - [Parameter()] - [System.String] - $SettingValueName, - - [Parameter()] - [System.String] - $SettingValueType, - - [Parameter()] - [System.String] - $SettingValueTemplateId - ) - - $settingValueReturn = @{} - switch ($settingType) - { - '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - { - $groupSettingCollectionValue = @{} - $groupSettingCollectionValueChildren = @() - - $groupSettingCollectionDefinitionChildren = $SettingDefinition.AdditionalProperties.groupSettingCollectionValueTemplate.children - foreach ($childDefinition in $groupSettingCollectionDefinitionChildren) - { - $childSettingName = $childDefinition.settingDefinitionId.split('_') | Select-Object -Last 1 - $childSettingType = $childDefinition.'@odata.type'.replace('InstanceTemplate', 'Instance') - $childSettingValueName = $childSettingType.replace('#microsoft.graph.deviceManagementConfiguration', '').replace('Instance', 'Value') - $childSettingValueType = "#microsoft.graph.deviceManagementConfiguration$($childSettingValueName)" - $childSettingValueName = $childSettingValueName.Substring(0, 1).ToLower() + $childSettingValueName.Substring(1, $childSettingValueName.length - 1 ) - $childSettingValueTemplateId = $childDefinition.$childSettingValueName.settingValueTemplateId - $childSettingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` - -DSCParams $DSCParams ` - -SettingDefinition $childDefinition ` - -SettingName $childSettingName ` - -SettingType $childDefinition.'@odata.type' ` - -SettingValueName $childSettingValueName ` - -SettingValueType $childSettingValueType ` - -SettingValueTemplateId $childSettingValueTemplateId - - if ($null -ne $childSettingValue) - { - $childSettingValue.add('settingDefinitionId', $childDefinition.settingDefinitionId) - $childSettingValue.add('@odata.type', $childSettingType ) - $groupSettingCollectionValueChildren += $childSettingValue - } - } - $groupSettingCollectionValue.add('children', $groupSettingCollectionValueChildren) - $settingValueReturn.Add('groupSettingCollectionValue', @($groupSettingCollectionValue)) - } - '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' - { - $values = @() - foreach ( $key in $DSCParams.Keys) - { - if ($settingName -eq ($key.tolower())) - { - $values = $DSCParams[$key] - break - } - } - $settingValueCollection = @() - foreach ($v in $values) - { - $settingValueCollection += @{ - value = $v - '@odata.type' = $settingValueType - } - } - $settingValueReturn.Add($settingValueName, $settingValueCollection) - } - Default - { - $value = $null - foreach ( $key in $DSCParams.Keys) - { - if ($settingName -eq ($key.tolower())) - { - $value = "$($SettingDefinition.settingDefinitionId)_$($DSCParams[$key])" - break - } - } - $settingValue = @{} - - if (-Not [string]::IsNullOrEmpty($settingValueType)) - { - $settingValue.add('@odata.type', $settingValueType) - } - if (-Not [string]::IsNullOrEmpty($settingValueTemplateId)) - { - $settingValue.Add('settingValueTemplateReference', @{'settingValueTemplateId' = $settingValueTemplateId }) - } - $settingValue.add('value', $value) - if ($null -eq $value) - { - return $null - } - $settingValueReturn.Add($settingValueName, $settingValue) - } - } - return $settingValueReturn -} Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.schema.mof index 0167a59699..0993bab8eb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager/MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.schema.mof @@ -35,7 +35,7 @@ class MSFT_IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager : OMI_B [Write, Description("This rule provides an extra layer of protection against ransomware."), ValueMap{"off", "block","audit", "warn"}, Values{"off", "block","audit", "warn"}] String UseAdvancedProtectionAgainstRansomware; [Write, Description("List of additional folders that need to be protected")] String ControlledFolderAccessProtectedFolders[]; [Write, Description("List of apps that have access to protected folders.")] String ControlledFolderAccessAllowedApplications[]; - [Write, Description("This rule enable Controlled folder access which protects your data by checking apps against a list of known, trusted apps.values 0:disable, 1:enable, 2:audit"), ValueMap{"0", "1","2"}, Values{"0", "1","2"}] String EnableControlledFolderAccess; + [Write, Description("This rule enable Controlled folder access which protects your data by checking apps against a list of known, trusted apps.values 0:disable, 1:enable, 2:audit, 3: Block disk modification only, 4: Audit disk modification only"), ValueMap{"0", "1", "2", "3", "4"}, Values{"0", "1", "2", "3", "4"}] String EnableControlledFolderAccess; [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 Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.Tests.ps1 index 4d5e9e8d1d..7f5ca15155 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.Tests.ps1 @@ -41,12 +41,52 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplate -MockWith { + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { return @{ - TemplateId = 'd02f2162-fcac-48db-9b7b-b0a3f160d2c2_1' + Id = 0 + SettingDefinitions = @( + @{ + Id = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware' + Name = 'UseAdvancedProtectionAgainstRansomware' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd770fcd1-62cd-4217-9b20-9ee2a12062ff' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @(@{ + children = @( + @{ + "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" + "settingDefinitionId" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware" + "choiceSettingValue" = @{ + "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" + "value" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block" + } + } + ) + }) + } + } + AdditionalProperties = $null } } @@ -66,32 +106,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } }) } + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { } - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -MockWith { - return @{ - Id = '12345-12345-12345-12345-12345' - SettingInstanceTemplate = @{ - settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' - settingInstanceTemplateId = 'd770fcd1-62cd-4217-9b20-9ee2a12062ff' - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstanceTemplate' - groupSettingCollectionValueTemplate = @{ - children =@( - @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstanceTemplate' - settingInstanceTemplateId ='999c8d1b-9f4e-49b7-824d-001c5c7d0182' - settingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware' - choiceSettingValueTemplate = @{ - settingValueTemplateId = 'a212472c-c5cc-43dd-898d-d35286a408e5' - } - } - ) - } - } - } - } - } # Mock Write-Host to hide output during the tests Mock -CommandName Write-Host -MockWith { @@ -161,37 +178,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Name = 'My Test' } } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = 'd770fcd1-62cd-4217-9b20-9ee2a12062ff' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - groupSettingCollectionValue = @(@{ - children = @( - @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - "settingDefinitionId" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware" - "choiceSettingValue" = @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - "value" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block" - } - } - ) - }) - } - } - AdditionalProperties = $null - } - } - Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { - } } It 'Should return Present from the Get method' { @@ -216,6 +202,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { DisplayName = 'My Test' Ensure = 'Present' Identity = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + useadvancedprotectionagainstransomware = 'block' Assignments = [CimInstance[]]@( (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ DataType = '#microsoft.graph.configurationManagerCollectionAssignmentTarget' @@ -231,35 +218,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Name = 'My Test' } } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = 'd770fcd1-62cd-4217-9b20-9ee2a12062ff' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - groupSettingCollectionValue = @(@{ - children = @( - @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - "settingDefinitionId" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware" - "choiceSettingValue" = @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - "value" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block" - } - } - ) - }) - } - } - AdditionalProperties = $null - } - } } It 'Should return true from the Test method' { @@ -290,35 +248,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Name = 'My Test' } } - - Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { - return @{ - Id = 0 - SettingDefinitions = $null - SettingInstance = @{ - SettingDefinitionId = 'device_vendor_msft_policy_config_defender_attacksurfacereductionrules' - SettingInstanceTemplateReference = @{ - SettingInstanceTemplateId = 'd770fcd1-62cd-4217-9b20-9ee2a12062ff' - } - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' - groupSettingCollectionValue = @(@{ - children = @( - @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance" - "settingDefinitionId" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware" - "choiceSettingValue" = @{ - "@odata.type" = "#microsoft.graph.deviceManagementConfigurationChoiceSettingValue" - "value" = "device_vendor_msft_policy_config_defender_attacksurfacereductionrules_useadvancedprotectionagainstransomware_block" - } - } - ) - }) - } - } - AdditionalProperties = $null - } - } } It 'Should return Present from the Get method' { From 555ee470f80dbc1c11d42a8913439e9b541d3183 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 18 Jul 2024 14:01:13 -0400 Subject: [PATCH 04/23] Removed unused variable --- Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 index 7ad66b8d6b..feea85d6f4 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 @@ -1599,7 +1599,6 @@ function Update-M365DSCAzureAdApplication $username = $Credential.UserName $password = $Credential.GetNetworkCredential().password - $url = "https://main.iam.ad.ext.azure.com/api/Directories/$($tenant.tenantId)/Details" $uri = 'https://login.microsoftonline.com/{0}/oauth2/token' -f $tenantid $body = 'resource=74658136-14ec-4630-ad9b-26e160ff0fc6&client_id=1950a258-227b-4e31-a9cf-717495945fc2&grant_type=password&username={1}&password={0}' -f [System.Web.HttpUtility]::UrlEncode($password), $username $token = Invoke-RestMethod $uri ` From bd24562ee8db5542a74f8b6e5532be71dfff99c3 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 12 Jun 2024 09:01:15 +0200 Subject: [PATCH 05/23] Update Intune Windows Update resource logic --- CHANGELOG.md | 8 + ...BusinessFeatureUpdateProfileWindows10.psm1 | 328 +++++++++++++++--- ...ssFeatureUpdateProfileWindows10.schema.mof | 4 +- .../readme.md | 21 ++ ...essFeatureUpdateProfileWindows10.Tests.ps1 | 253 ++++++++++---- 5 files changed, 493 insertions(+), 121 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 455cd4d420..a37820ad70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 + * Introduces new properties and updates the handling of the + start and end dates. + FIXES [#4614](https://github.com/microsoft/Microsoft365DSC/issues/4614) + FIXES [#3438](https://github.com/microsoft/Microsoft365DSC/issues/3438) + # 1.24.717.1 * AADConditionalAccessPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 index c77cbc0fa6..5130af0874 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 @@ -21,6 +21,14 @@ function Get-TargetResource [System.String] $FeatureUpdateVersion, + [Parameter()] + [System.Boolean] + $InstallFeatureUpdatesOptional, + + [Parameter()] + [System.Boolean] + $InstallLatestWindows10OnWindows11IneligibleDevice, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $RolloutSettings, @@ -94,8 +102,11 @@ function Get-TargetResource if (-Not [string]::IsNullOrEmpty($DisplayName)) { $getValue = Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile ` - -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue + -All ` + -ErrorAction SilentlyContinue | Where-Object ` + -FilterScript { + $_.DisplayName -eq $DisplayName + } } } #endregion @@ -126,21 +137,24 @@ function Get-TargetResource $results = @{ #region resource generator code - Description = $getValue.Description - DisplayName = $getValue.DisplayName - FeatureUpdateVersion = $getValue.FeatureUpdateVersion - RolloutSettings = $complexRolloutSettings - Id = $getValue.Id - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens + Description = $getValue.Description + DisplayName = $getValue.DisplayName + FeatureUpdateVersion = $getValue.FeatureUpdateVersion + InstallFeatureUpdatesOptional = $getValue.InstallFeatureUpdatesOptional + InstallLatestWindows10OnWindows11IneligibleDevice = $getValue.InstallLatestWindows10OnWindows11IneligibleDevice + RolloutSettings = $complexRolloutSettings + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens #endregion } + $assignmentsValues = Get-MgBetaDeviceManagementWindowsFeatureUpdateProfileAssignment -WindowsFeatureUpdateProfileId $Id $assignmentResult = @() if ($assignmentsValues.Count -gt 0) @@ -187,6 +201,14 @@ function Set-TargetResource [System.String] $FeatureUpdateVersion, + [Parameter()] + [System.Boolean] + $InstallFeatureUpdatesOptional, + + [Parameter()] + [System.Boolean] + $InstallLatestWindows10OnWindows11IneligibleDevice, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $RolloutSettings, @@ -242,43 +264,103 @@ function Set-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion + # Rollout is not "As soon as possible" + if ($null -ne $RolloutSettings) + { + # Rollout is either "On a specific date" or "gradually" + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferStartDateTimeInUTC)) + { + $currentTime = Get-Date + $offerStartDate = [datetime]::Parse($RolloutSettings.OfferStartDateTimeInUTC) + # Rollout is "On a specific date" + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferEndDateTimeInUTC)) + { + $offerEndDate = [datetime]::Parse($RolloutSettings.OfferEndDateTimeInUTC) + if ($offerEndDate -lt $offerStartDate.AddDays(1)) + { + throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' + } + + if ($offerEndDate -le $currentTime) + { + throw 'OfferEndDateTimeInUTC must be greater than the current time.' + } + } + } + } + $currentInstance = Get-TargetResource @PSBoundParameters + $BoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null - $PSBoundParameters.Remove('Verbose') | Out-Null - $PSBoundParameters.Remove('AccessTokens') | Out-Null + if ($null -eq $RolloutSettings) + { + $BoundParameters.RolloutSettings = @{ + OfferStartDateTimeInUTC = $null + OfferEndDateTimeInUTC = $null + OfferIntervalInDays = $null + } + } if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { Write-Verbose -Message "Creating an Intune Windows Update For Business Feature Update Profile for Windows10 with DisplayName {$DisplayName}" - $PSBoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('Assignments') | Out-Null - $CreateParameters = ([Hashtable]$PSBoundParameters).clone() + if ($null -ne $RolloutSettings) + { + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferStartDateTimeInUTC)) + { + $minTimeForAvailable = $currentTime + $newOfferStartDate = $offerStartDate + if ($offerStartDate -lt $minTimeForAvailable) + { + $newOfferStartDate = $minTimeForAvailable + $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') + } + + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferEndDateTimeInUTC)) + { + # If an end date is configured, then the start date must be greater than the current time + 2 days + $minTimeForAvailable = $currentTime.AddDays(2) + if ($newOfferStartDate -lt $minTimeForAvailable) + { + $newOfferStartDate = $minTimeForAvailable + $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') + } + + if ($offerEndDate -lt $newOfferStartDate) + { + throw 'OfferEndDateTimeInUTC must be greater than current time + 2 days.' + } + + if ($RolloutSettings.OfferIntervalInDays -gt ($offerEndDate - $newOfferStartDate).Days) + { + throw 'OfferIntervalInDays must be less than or equal to the difference between OfferEndDateTimeInUTC and OfferStartDateTimeInUTC in days.' + } + } + } + } + + $CreateParameters = ([Hashtable]$BoundParameters).Clone() $CreateParameters = Rename-M365DSCCimInstanceParameter -Properties $CreateParameters $CreateParameters.Remove('Id') | Out-Null - $keys = (([Hashtable]$CreateParameters).clone()).Keys + $keys = (([Hashtable]$CreateParameters).Clone()).Keys foreach ($key in $keys) { - if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.getType().Name -like '*cimInstance*') + 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.WindowsFeatureUpdateProfile") - $policy=New-MgBetaDeviceManagementWindowsFeatureUpdateProfile -BodyParameter $CreateParameters - $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + $policy = New-MgBetaDeviceManagementWindowsFeatureUpdateProfile -BodyParameter $CreateParameters - if ($policy.id) + if ($policy.Id) { - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.Id ` -Targets $assignmentsHash ` -Repository 'deviceManagement/windowsFeatureUpdateProfiles' } @@ -287,24 +369,83 @@ function Set-TargetResource elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Updating the Intune Windows Update For Business Feature Update Profile for Windows10 with Id {$($currentInstance.Id)}" - $PSBoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('Assignments') | Out-Null + $BoundParameters.Remove('InstallLatestWindows10OnWindows11IneligibleDevice') | Out-Null - $UpdateParameters = ([Hashtable]$PSBoundParameters).clone() - $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters + if ($null -ne $RolloutSettings) + { + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferStartDateTimeInUTC)) + { + $minTimeForAvailable = $currentTime + if (-not [string]::IsNullOrEmpty($currentInstance.RolloutSettings.OfferStartDateTimeInUTC)) + { + $currentOfferDate = [datetime]::Parse($currentInstance.RolloutSettings.OfferStartDateTimeInUTC) + } + else + { + $currentOfferDate = [datetime]::MinValue + } + $newOfferStartDate = $offerStartDate + # If the configured start date is different from the current start date and is less than the current time, we use the current start date + if ($offerStartDate -ne $currentOfferDate -and $offerStartDate -lt $minTimeForAvailable) + { + if ($currentOfferDate -eq [datetime]::MinValue) + { + $newOfferStartDate = $minTimeForAvailable + $currentOfferDate = $minTimeForAvailable + } + else + { + $newOfferStartDate = $currentOfferDate + } + $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $currentOfferDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') + } + + if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferEndDateTimeInUTC)) + { + # If an end date is configured, then the start date must be greater than the current time + 2 days + $offerEndDate = [datetime]::Parse($RolloutSettings.OfferEndDateTimeInUTC) + $minTimeForAvailable = $currentTime.AddDays(2) + if ($newOfferStartDate -lt $minTimeForAvailable) + { + $newOfferStartDate = $minTimeForAvailable + $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') + } + + if (-not [string]::IsNullOrEmpty($currentInstance.RolloutSettings.OfferEndDateTimeInUTC)) + { + $currentOfferEndDate = [datetime]::Parse($currentInstance.RolloutSettings.OfferEndDateTimeInUTC) + } + + # If the end date is less than the start date + 1 day or the current time, we throw an error + if ($offerEndDate -lt $newOfferStartDate.AddDays(1) -or $offerEndDate -lt $currentTime) + { + throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC and current time (+ 2 days if not previously specified).' + } + + if ($RolloutSettings.OfferIntervalInDays -gt ($offerEndDate - $newOfferStartDate).Days) + { + throw 'OfferIntervalInDays must be less than or equal to the difference between OfferEndDateTimeInUTC and OfferStartDateTimeInUTC in days.' + } + } + } + } + + $UpdateParameters = ([Hashtable]$BoundParameters).Clone() + $UpdateParameters = Rename-M365DSCCimInstanceParameter -Properties $UpdateParameters $UpdateParameters.Remove('Id') | Out-Null - $keys = (([Hashtable]$UpdateParameters).clone()).Keys + $keys = (([Hashtable]$UpdateParameters).Clone()).Keys foreach ($key in $keys) { - if ($null -ne $UpdateParameters.$key -and $UpdateParameters.$key.getType().Name -like '*cimInstance*') + 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.WindowsFeatureUpdateProfile") Update-MgBetaDeviceManagementWindowsFeatureUpdateProfile ` -WindowsFeatureUpdateProfileId $currentInstance.Id ` -BodyParameter $UpdateParameters @@ -347,6 +488,14 @@ function Test-TargetResource [System.String] $FeatureUpdateVersion, + [Parameter()] + [System.Boolean] + $InstallFeatureUpdatesOptional, + + [Parameter()] + [System.Boolean] + $InstallLatestWindows10OnWindows11IneligibleDevice, + [Parameter()] [Microsoft.Management.Infrastructure.CimInstance] $RolloutSettings, @@ -405,35 +554,112 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of the Intune Windows Update For Business Feature Update Profile for Windows10 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 - } + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() $testResult = $true + # Cannot be changed after creation + $ValuesToCheck.Remove('InstallLatestWindows10OnWindows11IneligibleDevice') | Out-Null + #Compare Cim instances foreach ($key in $PSBoundParameters.Keys) { + if ($key -eq 'RolloutSettings') + { + continue + } + $source = $PSBoundParameters.$key $target = $CurrentValues.$key - if ($source.getType().Name -like '*CimInstance*') + if ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') { $testResult = Compare-M365DSCComplexObject ` -Source ($source) ` -Target ($target) - if (-Not $testResult) + if (-not $testResult) { - $testResult = $false break } $ValuesToCheck.Remove($key) | Out-Null } } + + if (-not $testResult) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + + if (($null -eq $RolloutSettings -and $null -ne $CurrentValues.RolloutSettings) -or ` + ($null -ne $RolloutSettings -and $null -eq $CurrentValues.RolloutSettings)) + { + Write-Verbose -Message 'RolloutSettings is null in either the desired configuration or the current configuration.' + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + + $currentTime = Get-Date + [datetime]$offerStartDate = [datetime]::MinValue + [datetime]$offerEndDate = [datetime]::MinValue + [datetime]::TryParse($RolloutSettings.OfferStartDateTimeInUTC, [ref]$offerStartDate) | Out-Null + [datetime]::TryParse($RolloutSettings.OfferEndDateTimeInUTC, [ref]$offerEndDate) | Out-Null + if ($CurrentValues.Ensure -ne $Ensure) + { + if ($Ensure -eq 'Present') + { + if (($offerStartDate -ne [datetime]::MinValue -and $offerStartDate -lt $currentTime) ` + -and ($offerEndDate -ne [datetime]::MinValue -and $offerEndDate -lt $currentTime)) + { + Write-Verbose -Message "Start and end time are in the past, skip the configuration." + Write-Verbose -Message "Test-TargetResource returned $true" + return $true + } + } + + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + + [datetime]$currentOfferStartDate = [datetime]::MinValue + [datetime]$currentOfferEndDate = [datetime]::MinValue + [datetime]::TryParse($CurrentValues.RolloutSettings.OfferStartDateTimeInUTC, [ref]$currentOfferStartDate) | Out-Null + [datetime]::TryParse($CurrentValues.RolloutSettings.OfferEndDateTimeInUTC, [ref]$currentOfferEndDate) | Out-Null + if (($offerEndDate -eq [datetime]::MinValue -and $currentOfferEndDate -ne [datetime]::MinValue) -or ` + ($offerEndDate -ne [datetime]::MinValue -and $currentOfferEndDate -eq [datetime]::MinValue)) + { + Write-Verbose -Message 'OfferEndDateTimeInUTC is null in either the desired configuration or the current configuration.' + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + + if ($offerStartDate -ne [datetime]::MinValue -and $currentOfferStartDate -ne [datetime]::MinValue) + { + if ($offerStartDate -ne $currentOfferStartDate ` + -and $offerStartDate -gt $currentTime) + { + Write-Verbose -Message 'OfferStartDateTimeInUTC is different from current.' + $testResult = $false + } + + if ($testResult -and $offerEndDate -ne [datetime]::MinValue -and $currentOfferEndDate -ne [datetime]::MinValue) + { + if ($offerEndDate -ne $currentOfferEndDate ` + -and $offerEndDate -gt $currentTime ` + -and $offerEndDate -gt $offerStartDate) + { + Write-Verbose -Message 'OfferEndDateTimeInUTC is different from current.' + $testResult = $false + } + + if ($testResult -and $RolloutSettings.OfferIntervalInDays -ne $CurrentValues.RolloutSettings.OfferIntervalInDays) + { + Write-Verbose -Message 'OfferIntervalInDays is different from current.' + $testResult = $false + } + } + } + $ValuesToCheck.Remove('RolloutSettings') | Out-Null $ValuesToCheck.Remove('Id') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" @@ -554,7 +780,7 @@ function Export-TargetResource TenantId = $TenantId ApplicationSecret = $ApplicationSecret CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent + ManagedIdentity = $ManagedIdentity.IsPresent AccessTokens = $AccessTokens } @@ -565,7 +791,7 @@ function Export-TargetResource { $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` -ComplexObject $Results.RolloutSettings ` - -CIMInstanceName 'MicrosoftGraphwindowsUpdateRolloutSettings' + -CIMInstanceName 'MicrosoftGraphWindowsUpdateRolloutSettings' if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) { $Results.RolloutSettings = $complexTypeStringResult diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.schema.mof index f98952e13d..54b25eb0e0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.schema.mof @@ -23,7 +23,9 @@ class MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 : OMI_Bas [Key, Description("The display name of the profile.")] String DisplayName; [Write, Description("The description of the profile which is specified by the user.")] String Description; [Write, Description("The feature update version that will be deployed to the devices targeted by this profile. The version could be any supported version for example 1709, 1803 or 1809 and so on.")] String FeatureUpdateVersion; - [Write, Description("The windows update rollout settings, including offer start date time, offer end date time, and days between each set of offers."), EmbeddedInstance("MSFT_MicrosoftGraphwindowsUpdateRolloutSettings")] String RolloutSettings; + [Write, Description("If true, the Windows 11 update will become optional")] Boolean InstallFeatureUpdatesOptional; + [Write, Description("If true, the latest Microsoft Windows 10 update will be installed on devices ineligible for Microsoft Windows 11. Cannot be changed after creation of the policy.")] Boolean InstallLatestWindows10OnWindows11IneligibleDevice; + [Write, Description("The windows update rollout settings, including offer start date time, offer end date time, and days between each set of offers. For 'as soon as possible' installation, set this setting to $null or do not configure it."), EmbeddedInstance("MSFT_MicrosoftGraphwindowsUpdateRolloutSettings")] String RolloutSettings; [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; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md index 053226e059..deb95c3998 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md @@ -4,3 +4,24 @@ ## Description Intune Windows Update For Business Feature Update Profile for Windows10 + +## RolloutSettings + +The RolloutSettings for this resource have the following constraints and notes: + +* When creating a policy: + * If only a start date is specified, then the start date must be at least today. + * If the desired state date is before the current date, it will be adjusted to the current date. + * If a start and end date is specified, the start date must be the current date + 2 days, and + the end date must be at least one day after the start date. + * If the start date is before the current date + 2 days, it will be adjusted to this date. +* When updating a policy: + * If only a start date is specified, then the start date must either be the date from the current + configuration or the current date (or later). + * If the desired state date is before the current date, it will be adjusted to the current date. + * If a start and end date is specified, the start date must be the current date + 2 days, and + the end date must be at least one day after the start date. + * If the start date is before the current date + 2 days, it will be adjusted to this date. +* When testing a policy: + * If the policy is missing and the start and end date are before the current date, it will return true. + * If the start date is different but before the current start date and time, it will return true. \ No newline at end of file diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 index 490fca3de0..cf3abda18b 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 @@ -27,6 +27,24 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Confirm-M365DSCDependencies -MockWith { } + Mock -CommandName Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { + return @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = @{ + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } + } + } + + Mock -CommandName 'Get-Date' -MockWith { + return [datetime]::new(2022, 12, 30) + } + Mock -CommandName Update-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { } @@ -59,10 +77,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } -ClientOnly) + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) Ensure = 'Present' Credential = $Credential } @@ -91,47 +109,29 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } -ClientOnly) + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) Ensure = 'Absent' Credential = $Credential } - - Mock -CommandName Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { - return @{ - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.WindowsFeatureUpdateProfile' - } - Description = 'FakeStringValue' - DisplayName = 'FakeStringValue' - FeatureUpdateVersion = 'FakeStringValue' - Id = 'FakeStringValue' - RolloutSettings = @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } - - } - } } It 'Should return Values from the Get method' { (Get-TargetResource @testParams).Ensure | Should -Be 'Present' } - It 'Should return true from the Test method' { + It 'Should return false from the Test method' { Test-TargetResource @testParams | Should -Be $false } - It 'Should Remove the group from the Set method' { + It 'Should remove the profile from the Set method' { Set-TargetResource @testParams Should -Invoke -CommandName Remove-MgBetaDeviceManagementWindowsFeatureUpdateProfile -Exactly 1 } } - Context -Name 'The IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 Exists and Values are already in the desired state' -Fixture { + Context -Name 'The IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 exists and values are already in the desired state' -Fixture { BeforeAll { $testParams = @{ Description = 'FakeStringValue' @@ -139,34 +139,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } -ClientOnly) + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) Ensure = 'Present' Credential = $Credential } - - Mock -CommandName Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { - return @{ - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.WindowsFeatureUpdateProfile' - } - Description = 'FakeStringValue' - DisplayName = 'FakeStringValue' - FeatureUpdateVersion = 'FakeStringValue' - Id = 'FakeStringValue' - RolloutSettings = @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } - - } - } } - It 'Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true } @@ -180,10 +161,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 - } -ClientOnly) + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) Ensure = 'Present' Credential = $Credential } @@ -195,9 +176,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 7 + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 1 #drift } } } @@ -217,31 +198,165 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Context -Name 'ReverseDSC Tests' -Fixture { + Context -Name 'The IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 exists and the RolloutSettings are NOT in the desired state' -Fixture { BeforeAll { - $Global:CurrentModeIsExport = $true - $Global:PartialExportFileName = "$(New-Guid).partial.ps1" $testParams = @{ - Credential = $Credential + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential } + } + It 'Should return false from the Test method because OfferEndDateTimeInUTC is missing' { Mock -CommandName Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { return @{ - AdditionalProperties = @{ - '@odata.type' = '#microsoft.graph.WindowsFeatureUpdateProfile' - } Description = 'FakeStringValue' DisplayName = 'FakeStringValue' FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = @{ - OfferEndDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.0000000+00:00' - OfferIntervalInDays = 25 + OfferStartDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferEndDateTimeInUTC = $null + OfferIntervalInDays = $null } + } + } + Test-TargetResource @testParams | Should -Be $false + } + It 'Should return false from the Test method because neither OfferStartDateTimeInUTC nor OfferEndDateTimeInUTC is set' { + Mock -CommandName Get-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { + return @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = @{ + OfferEndDateTimeInUTC = $null + OfferStartDateTimeInUTC = $null + OfferIntervalInDays = $null + } } } + Test-TargetResource @testParams | Should -Be $false + } + } + + Context -Name 'The IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 exists and RolloutSettings are different but still valid' -Fixture { + It 'Should return true from the Test method because OfferStartDateTimeInUTC is before the current value and time' { + $testParams = @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2022-12-31T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential + } + Mock -CommandName 'Get-Date' -MockWith { + return [datetime]::new(2023, 1, 1) + } + Test-TargetResource @testParams | Should -Be $true + } + + It 'Should return true from the Test method because OfferStartDateTimeInUTC and OfferEndDateTimeInUTC are in the past' { + $testParams = @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential + } + + Mock -CommandName 'Get-Date' -MockWith { + return [datetime]::new(2023, 02, 02) + } + + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'The IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 exists and RolloutSettings are different and invalid' -Fixture { + It 'Should throw from the Set method because OfferStartDateTimeInUTC is after OfferEndDateTimeInUTC' { + $testParams = @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2023-01-04T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential + } + { Set-TargetResource @testParams } | Should -Throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' + } + + It 'Should throw from the Set method because OfferStartDateTimeInUTC is already set and OfferEndDateTimeInUTC is not greater than the current time' { + $testParams = @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 2 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential + } + Mock -CommandName 'Get-Date' -MockWith { + return [datetime]::new(2023, 1, 4) + } + { Set-TargetResource @testParams } | Should -Throw 'OfferEndDateTimeInUTC must be greater than the current time.' + } + + It 'Should throw from the Set method because OfferIntervalInDays is more than the gap between start and end time' { + $testParams = @{ + Description = 'FakeStringValue' + DisplayName = 'FakeStringValue' + FeatureUpdateVersion = 'FakeStringValue' + Id = 'FakeStringValue' + RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ + OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' + OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferIntervalInDays = 3 + } -ClientOnly) + Ensure = 'Present' + Credential = $Credential + } + { Set-TargetResource @testParams } | Should -Throw 'OfferIntervalInDays must be less than or equal to the difference between OfferEndDateTimeInUTC and OfferStartDateTimeInUTC in days.' + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } } It 'Should Reverse Engineer resource from the Export method' { $result = Export-TargetResource @testParams From 6caf01bf3ce7348f0a4257e0cfdd856081c33365 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Mon, 22 Jul 2024 12:50:30 +0000 Subject: [PATCH 06/23] Updated Resources and Cmdlet documentation pages --- ...neAttackSurfaceReductionRulesPolicyWindows10ConfigManager.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/intune/IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.md b/docs/docs/resources/intune/IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.md index 4c2dbf4fd5..205075bc84 100644 --- a/docs/docs/resources/intune/IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.md +++ b/docs/docs/resources/intune/IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager.md @@ -27,7 +27,7 @@ | **UseAdvancedProtectionAgainstRansomware** | Write | String | This rule provides an extra layer of protection against ransomware. | `off`, `block`, `audit`, `warn` | | **ControlledFolderAccessProtectedFolders** | Write | StringArray[] | List of additional folders that need to be protected | | | **ControlledFolderAccessAllowedApplications** | Write | StringArray[] | List of apps that have access to protected folders. | | -| **EnableControlledFolderAccess** | Write | String | This rule enable Controlled folder access which protects your data by checking apps against a list of known, trusted apps.values 0:disable, 1:enable, 2:audit | `0`, `1`, `2` | +| **EnableControlledFolderAccess** | Write | String | This rule enable Controlled folder access which protects your data by checking apps against a list of known, trusted apps.values 0:disable, 1:enable, 2:audit, 3: Block disk modification only, 4: Audit disk modification only | `0`, `1`, `2`, `3`, `4` | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Intune Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | From c2503511c1d7eaea591a919f480e472d7a5bb2a1 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Mon, 22 Jul 2024 14:10:47 +0200 Subject: [PATCH 07/23] Update feature update policy end date restrictions --- ...BusinessFeatureUpdateProfileWindows10.psm1 | 32 +++++----- .../readme.md | 2 +- ...essFeatureUpdateProfileWindows10.Tests.ps1 | 62 +++++++++---------- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 index 5130af0874..9fdd60d498 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.psm1 @@ -320,17 +320,18 @@ function Set-TargetResource if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferEndDateTimeInUTC)) { - # If an end date is configured, then the start date must be greater than the current time + 2 days + # If an end date is configured, then the start date must be at least the current time + 2 days $minTimeForAvailable = $currentTime.AddDays(2) if ($newOfferStartDate -lt $minTimeForAvailable) { + Write-Verbose -Message 'OfferStartDateTimeInUTC must be at least the current time + 2 days, adjusting it...' $newOfferStartDate = $minTimeForAvailable $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') } - if ($offerEndDate -lt $newOfferStartDate) + if ($offerEndDate -lt $newOfferStartDate.AddDays(1)) { - throw 'OfferEndDateTimeInUTC must be greater than current time + 2 days.' + throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' } if ($RolloutSettings.OfferIntervalInDays -gt ($offerEndDate - $newOfferStartDate).Days) @@ -387,7 +388,7 @@ function Set-TargetResource } $newOfferStartDate = $offerStartDate - # If the configured start date is different from the current start date and is less than the current time, we use the current start date + # If the configured start date is different from the current start date but less than the current time, we use the current start date if ($offerStartDate -ne $currentOfferDate -and $offerStartDate -lt $minTimeForAvailable) { if ($currentOfferDate -eq [datetime]::MinValue) @@ -399,29 +400,24 @@ function Set-TargetResource { $newOfferStartDate = $currentOfferDate } - $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $currentOfferDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') + $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') } if (-not [string]::IsNullOrEmpty($RolloutSettings.OfferEndDateTimeInUTC)) { - # If an end date is configured, then the start date must be greater than the current time + 2 days + # If an end date is configured, then the start date must be at least the current time + 2 days $offerEndDate = [datetime]::Parse($RolloutSettings.OfferEndDateTimeInUTC) $minTimeForAvailable = $currentTime.AddDays(2) if ($newOfferStartDate -lt $minTimeForAvailable) { + Write-Verbose -Message 'OfferStartDateTimeInUTC must be at least the current time + 2 days, adjusting it...' $newOfferStartDate = $minTimeForAvailable $BoundParameters.RolloutSettings.OfferStartDateTimeInUTC = $newOfferStartDate.ToString('yyyy-MM-ddTHH:mm:ss.fffZ') } - if (-not [string]::IsNullOrEmpty($currentInstance.RolloutSettings.OfferEndDateTimeInUTC)) - { - $currentOfferEndDate = [datetime]::Parse($currentInstance.RolloutSettings.OfferEndDateTimeInUTC) - } - - # If the end date is less than the start date + 1 day or the current time, we throw an error - if ($offerEndDate -lt $newOfferStartDate.AddDays(1) -or $offerEndDate -lt $currentTime) + if ($offerEndDate -lt $newOfferStartDate.AddDays(1)) { - throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC and current time (+ 2 days if not previously specified).' + throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' } if ($RolloutSettings.OfferIntervalInDays -gt ($offerEndDate - $newOfferStartDate).Days) @@ -644,6 +640,14 @@ function Test-TargetResource if ($testResult -and $offerEndDate -ne [datetime]::MinValue -and $currentOfferEndDate -ne [datetime]::MinValue) { + if ($offerStartDate -ne $currentOfferStartDate ` + -and $offerStartDate -gt $currentTime ` + -and $offerStartDate -lt $currentTime.AddDays(2)) + { + Write-Verbose -Message 'OfferStartDateTimeInUTC must be greater than the current time + 2 days to be changable if OfferEndDateTimeInUTC is specified, resetting testResult to true.' + $testResult = $true + } + if ($offerEndDate -ne $currentOfferEndDate ` -and $offerEndDate -gt $currentTime ` -and $offerEndDate -gt $offerStartDate) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md index deb95c3998..43ba886fcb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10/readme.md @@ -24,4 +24,4 @@ The RolloutSettings for this resource have the following constraints and notes: * If the start date is before the current date + 2 days, it will be adjusted to this date. * When testing a policy: * If the policy is missing and the start and end date are before the current date, it will return true. - * If the start date is different but before the current start date and time, it will return true. \ No newline at end of file + * If the start date is different but before the current start date or time, it will return true. diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 index cf3abda18b..da772471c5 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.Tests.ps1 @@ -34,15 +34,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } } } Mock -CommandName 'Get-Date' -MockWith { - return [datetime]::new(2022, 12, 30) + return [datetime]::new(2024, 01, 01) } Mock -CommandName Update-MgBetaDeviceManagementWindowsFeatureUpdateProfile -MockWith { @@ -77,8 +77,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -109,8 +109,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Absent' @@ -139,8 +139,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -161,8 +161,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -176,8 +176,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 1 #drift } } @@ -206,8 +206,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -223,7 +223,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = @{ - OfferStartDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferEndDateTimeInUTC = $null OfferIntervalInDays = $null } @@ -258,15 +258,15 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2022-12-31T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' Credential = $Credential } Mock -CommandName 'Get-Date' -MockWith { - return [datetime]::new(2023, 1, 1) + return [datetime]::new(2024, 1, 5) } Test-TargetResource @testParams | Should -Be $true } @@ -278,8 +278,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -287,7 +287,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName 'Get-Date' -MockWith { - return [datetime]::new(2023, 02, 02) + return [datetime]::new(2024, 02, 01) } Test-TargetResource @testParams | Should -Be $true @@ -302,8 +302,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-04T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-08T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' @@ -312,24 +312,24 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { { Set-TargetResource @testParams } | Should -Throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' } - It 'Should throw from the Set method because OfferStartDateTimeInUTC is already set and OfferEndDateTimeInUTC is not greater than the current time' { + It 'Should throw from the Set method because OfferStartDateTimeInUTC is adjusted and OfferEndDateTimeInUTC is not greater than that time + 1 day' { $testParams = @{ Description = 'FakeStringValue' DisplayName = 'FakeStringValue' FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 2 } -ClientOnly) Ensure = 'Present' Credential = $Credential } Mock -CommandName 'Get-Date' -MockWith { - return [datetime]::new(2023, 1, 4) + return [datetime]::new(2024, 1, 5) } - { Set-TargetResource @testParams } | Should -Throw 'OfferEndDateTimeInUTC must be greater than the current time.' + { Set-TargetResource @testParams } | Should -Throw 'OfferEndDateTimeInUTC must be greater than OfferStartDateTimeInUTC + 1 day.' } It 'Should throw from the Set method because OfferIntervalInDays is more than the gap between start and end time' { @@ -339,8 +339,8 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { FeatureUpdateVersion = 'FakeStringValue' Id = 'FakeStringValue' RolloutSettings = (New-CimInstance -ClassName MSFT_MicrosoftGraphwindowsUpdateRolloutSettings -Property @{ - OfferStartDateTimeInUTC = '2023-01-01T00:00:00.000Z' - OfferEndDateTimeInUTC = '2023-01-03T00:00:00.000Z' + OfferStartDateTimeInUTC = '2024-01-05T00:00:00.000Z' + OfferEndDateTimeInUTC = '2024-01-07T00:00:00.000Z' OfferIntervalInDays = 3 } -ClientOnly) Ensure = 'Present' From ebf8447c5bb457fc2f915f1398ad44ba3fb88e61 Mon Sep 17 00:00:00 2001 From: mlhickey Date: Mon, 22 Jul 2024 08:24:06 -0700 Subject: [PATCH 08/23] Update M365DSCUtil.psm1 Add support for credential & application ID to address #4791 --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 882674e3a4..1411a55cac 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1304,6 +1304,7 @@ function Export-M365DSCConfiguration if ($PSBoundParameters.ContainsKey('ApplicationId') -eq $true -and ` $PSBoundParameters.ContainsKey('TenantId') -eq $true -and ` + $PSBoundParameters.ContainsKey('Credential') -eq $false -and ` ($PSBoundParameters.ContainsKey('CertificateThumbprint') -eq $false -and ` $PSBoundParameters.ContainsKey('ApplicationSecret') -eq $false -and ` $PSBoundParameters.ContainsKey('CertificatePath') -eq $false)) From 3deb7b67e8cf38f55f8b1e06143613edb92cf0e1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 22 Jul 2024 14:38:04 -0400 Subject: [PATCH 09/23] Fixes issue with SPOSharingSettings Filtering --- CHANGELOG.md | 6 ++++-- .../MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74310e3917..e3b18c58a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,12 @@ # Change log for Microsoft365DSC -# UNRELEASED +# UNRELEASED * IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager - * Migrate to new settings catalog cmdlets. + * Migrate to new settings catalog cmdlets. FIXES [#3966](https://github.com/microsoft/Microsoft365DSC/issues/3966) +* SPOSharingSettings + * Changed approach to MySite filtering. # 1.24.717.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 index f412d6b79f..da02a82def 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 @@ -173,7 +173,7 @@ function Get-TargetResource try { $SPOSharingSettings = Get-PnPTenant -ErrorAction Stop - $MySite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.' -and Template -notlike '^RedirectSite#'" + $MySite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#'" } if ($null -ne $MySite) { @@ -532,7 +532,7 @@ function Set-TargetResource Set-PnPTenant @CurrentParameters | Out-Null if ($SetMySharingCapability) { - $mysite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.' -and Template -notlike '^RedirectSite#'" + $mysite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#'" } Set-PnPTenantSite -Identity $mysite.Url -SharingCapability $MySiteSharingCapability } } From 103bf9e9b746f9a7cb2351c58c6d9f80426f8f8e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 22 Jul 2024 15:12:30 -0400 Subject: [PATCH 10/23] Additional fix for Template Filter --- .../MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 index da02a82def..e0bccf5548 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 @@ -173,7 +173,7 @@ function Get-TargetResource try { $SPOSharingSettings = Get-PnPTenant -ErrorAction Stop - $MySite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#'" } + $MySite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#" } if ($null -ne $MySite) { @@ -532,7 +532,7 @@ function Set-TargetResource Set-PnPTenant @CurrentParameters | Out-Null if ($SetMySharingCapability) { - $mysite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#'" } + $mysite = Get-PnPTenantSite -Filter "Url -like '-my.sharepoint.'" | Where-Object -FilterScript { $_.Template -notmatch "^RedirectSite#" } Set-PnPTenantSite -Identity $mysite.Url -SharingCapability $MySiteSharingCapability } } From 25c93c796470aa5733fb9fa990ad76f19493bc1d Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 23 Jul 2024 11:11:56 +0000 Subject: [PATCH 11/23] Updated Resources and Cmdlet documentation pages --- ...orBusinessFeatureUpdateProfileWindows10.md | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/docs/resources/intune/IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.md b/docs/docs/resources/intune/IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.md index 6bd3ae2629..2c6cec626d 100644 --- a/docs/docs/resources/intune/IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.md +++ b/docs/docs/resources/intune/IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10.md @@ -8,7 +8,9 @@ | **DisplayName** | Key | String | The display name of the profile. | | | **Description** | Write | String | The description of the profile which is specified by the user. | | | **FeatureUpdateVersion** | Write | String | The feature update version that will be deployed to the devices targeted by this profile. The version could be any supported version for example 1709, 1803 or 1809 and so on. | | -| **RolloutSettings** | Write | MSFT_MicrosoftGraphwindowsUpdateRolloutSettings | The windows update rollout settings, including offer start date time, offer end date time, and days between each set of offers. | | +| **InstallFeatureUpdatesOptional** | Write | Boolean | If true, the Windows 11 update will become optional | | +| **InstallLatestWindows10OnWindows11IneligibleDevice** | Write | Boolean | If true, the latest Microsoft Windows 10 update will be installed on devices ineligible for Microsoft Windows 11. Cannot be changed after creation of the policy. | | +| **RolloutSettings** | Write | MSFT_MicrosoftGraphwindowsUpdateRolloutSettings | The windows update rollout settings, including offer start date time, offer end date time, and days between each set of offers. For 'as soon as possible' installation, set this setting to $null or do not configure it. | | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Admin | | @@ -47,6 +49,27 @@ Intune Windows Update For Business Feature Update Profile for Windows10 +## RolloutSettings + +The RolloutSettings for this resource have the following constraints and notes: + +* When creating a policy: + * If only a start date is specified, then the start date must be at least today. + * If the desired state date is before the current date, it will be adjusted to the current date. + * If a start and end date is specified, the start date must be the current date + 2 days, and + the end date must be at least one day after the start date. + * If the start date is before the current date + 2 days, it will be adjusted to this date. +* When updating a policy: + * If only a start date is specified, then the start date must either be the date from the current + configuration or the current date (or later). + * If the desired state date is before the current date, it will be adjusted to the current date. + * If a start and end date is specified, the start date must be the current date + 2 days, and + the end date must be at least one day after the start date. + * If the start date is before the current date + 2 days, it will be adjusted to this date. +* When testing a policy: + * If the policy is missing and the start and end date are before the current date, it will return true. + * If the start date is different but before the current start date or time, it will return true. + ## Permissions ### Microsoft Graph From cdd496987e871b262c3c2c4361d7ff4d2554ce14 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 23 Jul 2024 11:13:16 +0000 Subject: [PATCH 12/23] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index ee276441d1..dca6c52ecd 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -32852,6 +32852,16 @@ "Name": "FeatureUpdateVersion", "Option": "Write" }, + { + "CIMType": "Boolean", + "Name": "InstallFeatureUpdatesOptional", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "InstallLatestWindows10OnWindows11IneligibleDevice", + "Option": "Write" + }, { "CIMType": "MSFT_MicrosoftGraphwindowsUpdateRolloutSettings", "Name": "RolloutSettings", From 7e5f7e55fab07f3f4bd1dbe14ebc276da4f48245 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 23 Jul 2024 11:29:32 +0000 Subject: [PATCH 13/23] Updated Resources and Cmdlet documentation pages --- .../intune/IntuneAntivirusPolicyWindows10SettingCatalog.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md b/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md index 535b6c4d86..2ad9520438 100644 --- a/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md +++ b/docs/docs/resources/intune/IntuneAntivirusPolicyWindows10SettingCatalog.md @@ -51,6 +51,7 @@ | **disablecatchupquickscan** | Write | String | This policy setting allows you to configure catch-up scans for scheduled quick scans. (1: disabled, 0: enabled) | `0`, `1` | | **disablednsovertcpparsing** | Write | String | Disables or enables DNS over TCP Parsing for Network Protection. (0: enable feature. 1: disable feature) | `0`, `1` | | **disablehttpparsing** | Write | String | Disables or enables HTTP Parsing for Network Protection. (0: enable feature. 1: disable feature) | `0`, `1` | +| **DisableSshParsing** | Write | String | Disable Ssh Parsing (1: SSH parsing is disabled, 0: SSH parsing is enabled) | `1`, `0` | | **enablelowcpupriority** | Write | String | This policy setting allows you to enable or disable low CPU priority for scheduled scans. (0: disable feature. 1: enable feature) | `0`, `1` | | **enablenetworkprotection** | Write | String | This policy allows you to turn on network protection (block/audit) or off. (0: disabled, 1: block mode, 2: audit mode) | `0`, `1`, `2` | | **excludedextensions** | Write | StringArray[] | Allows an administrator to specify a list of file type extensions to ignore during a scan. | | @@ -65,13 +66,13 @@ | **scanparameter** | Write | String | Selects whether to perform a quick scan or full scan. (1: Quick scan, 2: Full scan) | `1`, `2` | | **schedulequickscantime** | Write | SInt32 | Selects the time of day that the Windows Defender quick scan should run. | | | **schedulescanday** | Write | String | Selects the day that the Windows Defender scan should run. (0: Every day, 1: Sunday, 2: Monday, 3: Tuesday, 4: Wednesday, 5: Thursday, 6: Friday, 7: Saturday, 8: No scheduled scan) | `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8` | -| **schedulescantime** | Write | SInt32 | Selects the time of day that the Windows Defender scan should run. | | +| **schedulescantime** | Write | SInt32 | Selects the time of day that the Windows Defender scan should run. Must be between 0 and 1380 minutes. | | | **disabletlsparsing** | Write | String | This setting disables TLS Parsing for Network Protection. (0: enabled, 1: disabled) | `0`, `1` | | **randomizescheduletasktimes** | Write | String | Specifies if the start time of the scan is randomized. (0: no randomization, 1: randomized) | `0`, `1` | | **schedulerrandomizationtime** | Write | SInt32 | This setting allows you to configure the scheduler randomization in hours. The randomization interval is [1 - 23] hours. | | | **signatureupdatefallbackorder** | Write | StringArray[] | This policy setting allows you to define the order in which different definition update sources should be contacted. | | | **signatureupdatefilesharessources** | Write | StringArray[] | This policy setting allows you to configure UNC file share sources for downloading definition updates. | | -| **signatureupdateinterval** | Write | SInt32 | Specifies the interval (in hours) that will be used to check for signatures, so instead of using the ScheduleDay and ScheduleTime the check for new signatures will be set according to the interval. | | +| **signatureupdateinterval** | Write | SInt32 | Specifies the interval (in hours) that will be used to check for signatures, so instead of using the ScheduleDay and ScheduleTime the check for new signatures will be set according to the interval. Must be between 0 and 24 hours. | | | **submitsamplesconsent** | Write | String | Checks for the user consent level in Windows Defender to send data. (0: Always prompt, 1: Send safe samples automatically, 2: Never send, 3: Send all samples automatically) | `0`, `1`, `2`, `3` | | **disablelocaladminmerge** | Write | String | This policy setting controls whether or not complex list settings configured by a local administrator are merged with managed settings. (0: enable local admin merge, 1: disable local admin merge) | `0`, `1` | | **allowonaccessprotection** | Write | String | Allows or disallows Windows Defender On Access Protection functionality. (0: disable feature. 1: enable feature) | `0`, `1` | @@ -79,7 +80,7 @@ | **moderateseveritythreats** | Write | String | Allows an administrator to specify moderate severity threats corresponding action ID to take. | `clean`, `quarantine`, `remove`, `allow`, `userdefined`, `block` | | **severethreats** | Write | String | Allows an administrator to specify high severity threats corresponding action ID to take. | `clean`, `quarantine`, `remove`, `allow`, `userdefined`, `block` | | **highseveritythreats** | Write | String | Allows an administrator to specify severe threats corresponding action ID to take. | `clean`, `quarantine`, `remove`, `allow`, `userdefined`, `block` | -| **templateId** | Write | String | Template Id of the policy. | `d948ff9b-99cb-4ee0-8012-1fbc09685377_1`, `e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1`, `45fea5e9-280d-4da1-9792-fb5736da0ca9_1`, `804339ad-1553-4478-a742-138fb5807418_1` | +| **templateId** | Write | String | Template Id of the policy. 0: Windows Security Experience, 1: Defender Update controls, 2: Microsoft Defender Antivirus exclusions, 3: Microsoft Defender Antivirus | `d948ff9b-99cb-4ee0-8012-1fbc09685377_1`, `e3f74c5a-a6de-411d-aef6-eb15628f3a0a_1`, `45fea5e9-280d-4da1-9792-fb5736da0ca9_1`, `804339ad-1553-4478-a742-138fb5807418_1` | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Intune Admin | | From dc8a3d1dcb88096adc52bcb13d69f5f71494454f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 23 Jul 2024 11:31:27 +0000 Subject: [PATCH 14/23] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index dca6c52ecd..5c9de6a8f1 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -16032,6 +16032,11 @@ "Name": "disablehttpparsing", "Option": "Write" }, + { + "CIMType": "String", + "Name": "DisableSshParsing", + "Option": "Write" + }, { "CIMType": "String", "Name": "enablelowcpupriority", From ab16ddab75596e997c9e332ca0787d7005bca74e Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 23 Jul 2024 14:41:02 +0200 Subject: [PATCH 15/23] Add Intune EDR Linux Profile --- CHANGELOG.md | 2 + ...dpointDetectionAndResponsePolicyLinux.psm1 | 618 ++++++++++++++++++ ...DetectionAndResponsePolicyLinux.schema.mof | 30 + .../readme.md | 6 + .../settings.json | 32 + .../1-Create.ps1 | 39 ++ .../2-Update.ps1 | 38 ++ .../3-Remove.ps1 | 34 + ...tDetectionAndResponsePolicyLinux.Tests.ps1 | 367 +++++++++++ 9 files changed, 1166 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyLinux.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6be603ba97..b08e11d163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager * Migrate to new settings catalog cmdlets. FIXES [#3966](https://github.com/microsoft/Microsoft365DSC/issues/3966) +* IntuneEndpointDetectionAndResponsePolicyLinux + * Initial release. * IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 * Introduces new properties and updates the handling of the start and end dates. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.psm1 new file mode 100644 index 0000000000..a2a7a9622f --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.psm1 @@ -0,0 +1,618 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + 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-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy Linux with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy Linux with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Endpoint Detection And Response Policy Linux with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $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(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $templateReferenceId = '3514388a-d4d1-4aa8-bd64-c317776008f5_1' + $platforms = 'linux' + $technologies = 'microsoftSense' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Endpoint Detection And Response Policy Linux with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Endpoint Detection And Response Policy Linux with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Endpoint Detection And Response Policy Linux with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 Endpoint Detection And Response Policy Linux with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + 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 ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + 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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $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 + $policyTemplateID = "3514388a-d4d1-4aa8-bd64-c317776008f5_1" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #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 + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + 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.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_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.schema.mof new file mode 100644 index 0000000000..9802a097e5 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux.schema.mof @@ -0,0 +1,30 @@ +[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.0"), FriendlyName("IntuneEndpointDetectionAndResponsePolicyLinux")] +class MSFT_IntuneEndpointDetectionAndResponsePolicyLinux : OMI_BaseResource +{ + [Key, Description("Policy name")] String DisplayName; + [Write, Description("Policy description")] String Description; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Value of tag")] String tags_item_value; + [Write, Description("Type of tag (0: GROUP)"), ValueMap{"0"}, Values{"0"}] String tags_item_key; + [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; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/readme.md new file mode 100644 index 0000000000..980dc6de67 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/readme.md @@ -0,0 +1,6 @@ + +# IntuneEndpointDetectionAndResponsePolicyLinux + +## Description + +Intune Endpoint Detection And Response Policy Linux diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/settings.json new file mode 100644 index 0000000000..84a108a641 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyLinux/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName":"IntuneEndpointDetectionAndResponsePolicyLinux", + "description":"This resource configures an Intune Endpoint Detection And Response Policy Linux.", + "permissions":{ + "graph":{ + "delegated":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "application":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/1-Create.ps1 new file mode 100644 index 0000000000..6671471279 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/1-Create.ps1 @@ -0,0 +1,39 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/2-Update.ps1 new file mode 100644 index 0000000000..d9b9df2105 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My updated description' # Updated Property + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/3-Remove.ps1 new file mode 100644 index 0000000000..e366ce677a --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyLinux/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyLinux.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyLinux.Tests.ps1 new file mode 100644 index 0000000000..02453092ee --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyLinux.Tests.ps1 @@ -0,0 +1,367 @@ +[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 "IntuneEndpointDetectionAndResponsePolicyLinux" -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-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_edr_tags' + Name = 'tags' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + } + }, + @{ + Id = 'linux_mdatp_managed_edr_tags_item_value' + Name = 'tags_item_value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + }, + @{ + Id = 'linux_mdatp_managed_edr_tags_item_key' + Name = 'tags_item_key' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_edr_tags' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd0eb0a92-3807-4d9d-8432-6edd1aa108ce' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + settingValueTemplateReference = $null + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstance' + children = @() + value = 'linux_mdatp_managed_edr_tags_item_key_0' + } + settingDefinitionId = 'linux_mdatp_managed_edr_tags_item_key' + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = 'tag' + } + settingDefinitionId = 'linux_mdatp_managed_edr_tags_item_value' + } + ) + } + ) + } + } + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + Description = 'My Test Description' + Name = 'My Test' + TemplateReference = @{ + TemplateId = '3514388a-d4d1-4aa8-bd64-c317776008f5_1' + TemplateFamily = 'endpointSecurityEndpointDetectionAndResponse' + } + RoleScopeTagIds = @("FakeStringValue") + } + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + } + # Test contexts + Context -Name "The IntuneEndpointDetectionAndResponsePolicyLinux should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneEndpointDetectionAndResponsePolicyLinux exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Absent' + Credential = $Credential; + } + } + + 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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneEndpointDetectionAndResponsePolicyLinux Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneEndpointDetectionAndResponsePolicyLinux exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_edr_tags' + Name = 'tags' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + } + }, + @{ + Id = 'linux_mdatp_managed_edr_tags_item_value' + Name = 'tags_item_value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + }, + @{ + Id = 'linux_mdatp_managed_edr_tags_item_key' + Name = 'tags_item_key' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_edr_tags' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd0eb0a92-3807-4d9d-8432-6edd1aa108ce' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + settingValueTemplateReference = $null + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstance' + children = @() + value = 'linux_mdatp_managed_edr_tags_item_key_0' + } + settingDefinitionId = 'linux_mdatp_managed_edr_tags_item_key' + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = 'tag1234' #drift + } + settingDefinitionId = 'linux_mdatp_managed_edr_tags_item_value' + } + ) + } + ) + } + } + } + } + } + + 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-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From ba7cfdc074b4d7909edc121ee3944cabc9c5e792 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 23 Jul 2024 14:49:37 +0200 Subject: [PATCH 16/23] Add Intune EDR MacOS Profile --- CHANGELOG.md | 2 + ...dpointDetectionAndResponsePolicyMacOS.psm1 | 618 ++++++++++++++++++ ...DetectionAndResponsePolicyMacOS.schema.mof | 30 + .../readme.md | 6 + .../settings.json | 32 + .../1-Create.ps1 | 39 ++ .../2-Update.ps1 | 38 ++ .../3-Remove.ps1 | 34 + ...tDetectionAndResponsePolicyMacOS.Tests.ps1 | 368 +++++++++++ 9 files changed, 1167 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyMacOS.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6be603ba97..4a3e06e879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager * Migrate to new settings catalog cmdlets. FIXES [#3966](https://github.com/microsoft/Microsoft365DSC/issues/3966) +* IntuneEndointDetectionAndResponsePolicyMacOS + * Initial release. * IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 * Introduces new properties and updates the handling of the start and end dates. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.psm1 new file mode 100644 index 0000000000..71d557da8b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.psm1 @@ -0,0 +1,618 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + 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-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Id -ErrorAction SilentlyContinue + + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy MacOS with Id {$Id}" + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter "Name eq '$DisplayName'" ` + -ErrorAction SilentlyContinue + } + } + #endregion + if ($null -eq $getValue) + { + Write-Verbose -Message "Could not find an Intune Endpoint Detection And Response Policy MacOS with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Endpoint Detection And Response Policy MacOS with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -ErrorAction Stop + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + #endregion + } + $results += $policySettings + + $assignmentsValues = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $Id + $assignmentResult = @() + if ($assignmentsValues.Count -gt 0) + { + $assignmentResult += ConvertFrom-IntunePolicyAssignment -Assignments $assignmentsValues -IncludeDeviceFilter $true + } + $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(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 + + $templateReferenceId = 'a6ff37f6-c841-4264-9249-1ecf793d94ef_1' + $platforms = 'macOS' + $technologies = 'microsoftSense' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Endpoint Detection And Response Policy MacOS with Name {$DisplayName}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + $createParameters = @{ + Name = $DisplayName + Description = $Description + TemplateReference = @{ templateId = $templateReferenceId } + Platforms = $platforms + Technologies = $technologies + Settings = $settings + } + + #region resource generator code + $policy = New-MgBetaDeviceManagementConfigurationPolicy -BodyParameter $createParameters + + if ($policy.Id) + { + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $policy.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + } + #endregion + } + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Updating the Intune Endpoint Detection And Response Policy MacOS with Id {$($currentInstance.Id)}" + $BoundParameters.Remove("Assignments") | Out-Null + + $settings = Get-IntuneSettingCatalogPolicySetting ` + -DSCParams ([System.Collections.Hashtable]$BoundParameters) ` + -TemplateId $templateReferenceId + + Update-IntuneDeviceConfigurationPolicy ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Name $DisplayName ` + -Description $Description ` + -TemplateReferenceId $templateReferenceId ` + -Platforms $platforms ` + -Technologies $technologies ` + -Settings $settings + + #region resource generator code + $assignmentsHash = ConvertTo-IntunePolicyAssignment -IncludeDeviceFilter:$true -Assignments $Assignments + Update-DeviceConfigurationPolicyAssignment ` + -DeviceConfigurationPolicyId $currentInstance.Id ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/configurationPolicies' + #endregion + } + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing the Intune Endpoint Detection And Response Policy MacOS with Id {$($currentInstance.Id)}" + #region resource generator code + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentInstance.Id + #endregion + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + #region resource generator code + [Parameter()] + [System.String] + $Description, + + [Parameter(Mandatory = $true)] + [System.String] + $DisplayName, + + [Parameter()] + [System.String[]] + $RoleScopeTagIds, + + [Parameter()] + [System.String] + $Id, + + [Parameter()] + [System.String] + $tags_item_value, + + [Parameter()] + [ValidateSet('0')] + [System.String] + $tags_item_key, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #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 Endpoint Detection And Response Policy MacOS with Id {$Id} and Name {$DisplayName}" + + $CurrentValues = Get-TargetResource @PSBoundParameters + [Hashtable]$ValuesToCheck = @{} + $MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + if ($_.Key -notlike '*Variable' -or $_.Key -notin @('Verbose', 'Debug', 'ErrorAction', 'WarningAction', 'InformationAction')) + { + if ($null -ne $CurrentValues[$_.Key] -or $null -ne $PSBoundParameters[$_.Key]) + { + $ValuesToCheck.Add($_.Key, $null) + if (-not $PSBoundParameters.ContainsKey($_.Key)) + { + $PSBoundParameters.Add($_.Key, $null) + } + } + } + } + + 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 ($null -ne $source -and $source.GetType().Name -like '*CimInstance*') + { + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if (-not $testResult) + { + break + } + + $ValuesToCheck.Remove($key) | Out-Null + } + } + + $ValuesToCheck.Remove('Id') | Out-Null + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + 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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $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 + $policyTemplateID = "a6ff37f6-c841-4264-9249-1ecf793d94ef_1" + [array]$getValue = Get-MgBetaDeviceManagementConfigurationPolicy ` + -Filter $Filter ` + -All ` + -ErrorAction Stop | Where-Object ` + -FilterScript { + $_.TemplateReference.TemplateId -eq $policyTemplateID + } + #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 + } + elseif (-not [string]::IsNullOrEmpty($config.name)) + { + $displayedKey = $config.name + } + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.Name + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + 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.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_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.schema.mof new file mode 100644 index 0000000000..de1901f0c5 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS.schema.mof @@ -0,0 +1,30 @@ +[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.0"), FriendlyName("IntuneEndpointDetectionAndResponsePolicyMacOS")] +class MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS : OMI_BaseResource +{ + [Key, Description("Policy name")] String DisplayName; + [Write, Description("Policy description")] String Description; + [Write, Description("List of Scope Tags for this Entity instance.")] String RoleScopeTagIds[]; + [Write, Description("The unique identifier for an entity. Read-only.")] String Id; + [Write, Description("Value of tag")] String tags_item_value; + [Write, Description("Type of tag (0: GROUP)"), ValueMap{"0"}, Values{"0"}] String tags_item_key; + [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; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/readme.md new file mode 100644 index 0000000000..413a87b016 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/readme.md @@ -0,0 +1,6 @@ + +# IntuneEndpointDetectionAndResponsePolicyMacOS + +## Description + +Intune Endpoint Detection And Response Policy MacOS diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/settings.json new file mode 100644 index 0000000000..e948d6df87 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS/settings.json @@ -0,0 +1,32 @@ +{ + "resourceName":"IntuneEndpointDetectionAndResponsePolicyMacOS", + "description":"This resource configures an Intune Endpoint Detection And Response Policy MacOS.", + "permissions":{ + "graph":{ + "delegated":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + }, + "application":{ + "read":[ + { + "name":"DeviceManagementConfiguration.Read.All" + } + ], + "update":[ + { + "name":"DeviceManagementConfiguration.ReadWrite.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/1-Create.ps1 new file mode 100644 index 0000000000..821f2e2596 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/1-Create.ps1 @@ -0,0 +1,39 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/2-Update.ps1 new file mode 100644 index 0000000000..d522f0b5d2 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/2-Update.ps1 @@ -0,0 +1,38 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My updated description' # Updated Property + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/3-Remove.ps1 new file mode 100644 index 0000000000..d5be42ddbe --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneEndpointDetectionAndResponsePolicyMacOS/3-Remove.ps1 @@ -0,0 +1,34 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyMacOS.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyMacOS.Tests.ps1 new file mode 100644 index 0000000000..344ee94756 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneEndpointDetectionAndResponsePolicyMacOS.Tests.ps1 @@ -0,0 +1,368 @@ +[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 "IntuneEndpointDetectionAndResponsePolicyMacOS" -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-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName New-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'com.apple.managedclient.preferences_tags' + Name = 'tags' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + } + }, + @{ + Id = 'com.apple.managedclient.preferences_tags_item_value' + Name = 'tags_item_value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + }, + @{ + Id = 'com.apple.managedclient.preferences_tags_item_key' + Name = 'tags_item_key' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'com.apple.managedclient.preferences_tags' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd0eb0a92-3807-4d9d-8432-6edd1aa108ce' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + settingValueTemplateReference = $null + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstance' + children = @() + value = 'com.apple.managedclient.preferences_tags_item_key_0' + } + settingDefinitionId = 'com.apple.managedclient.preferences_tags_item_key' + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = 'tag' + } + settingDefinitionId = 'com.apple.managedclient.preferences_tags_item_value' + } + ) + } + ) + } + } + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + Description = 'My Test Description' + Name = 'My Test' + TemplateReference = @{ + TemplateId = 'a6ff37f6-c841-4264-9249-1ecf793d94ef_1' + TemplateFamily = 'endpointSecurityEndpointDetectionAndResponse' + } + RoleScopeTagIds = @("FakeStringValue") + } + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyAssignment -MockWith { + return @(@{ + Id = '12345-12345-12345-12345-12345' + Source = 'direct' + SourceId = '12345-12345-12345-12345-12345' + Target = @{ + DeviceAndAppManagementAssignmentFilterId = '12345-12345-12345-12345-12345' + DeviceAndAppManagementAssignmentFilterType = 'none' + AdditionalProperties = @( + @{ + '@odata.type' = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } + ) + } + }) + } + + } + # Test contexts + Context -Name "The IntuneEndpointDetectionAndResponsePolicyMacOS should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = "Present" + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + + Context -Name "The IntuneEndpointDetectionAndResponsePolicyMacOS exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Absent' + Credential = $Credential; + } + } + + 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-MgBetaDeviceManagementConfigurationPolicy -Exactly 1 + } + } + Context -Name "The IntuneEndpointDetectionAndResponsePolicyMacOS Exists and Values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneEndpointDetectionAndResponsePolicyMacOS exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + Assignments = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_DeviceManagementConfigurationPolicyAssignments -Property @{ + DataType = '#microsoft.graph.exclusionGroupAssignmentTarget' + groupId = '26d60dd1-fab6-47bf-8656-358194c1a49d' + } -ClientOnly) + ) + Description = 'My Test Description' + Id = '619bd4a4-3b3b-4441-bd6f-3f4c0c444870' + DisplayName = 'My Test' + tags_item_key = '0' + tags_item_value = 'tag' + RoleScopeTagIds = @("FakeStringValue") + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'com.apple.managedclient.preferences_tags' + Name = 'tags' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + } + }, + @{ + Id = 'com.apple.managedclient.preferences_tags_item_value' + Name = 'tags_item_value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + }, + @{ + Id = 'com.apple.managedclient.preferences_tags_item_key' + Name = 'tags_item_key' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'com.apple.managedclient.preferences_tags' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd0eb0a92-3807-4d9d-8432-6edd1aa108ce' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + settingValueTemplateReference = $null + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingInstance' + children = @() + value = 'com.apple.managedclient.preferences_tags_item_key_0' + } + settingDefinitionId = 'com.apple.managedclient.preferences_tags_item_key' + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = 'tag1234' #drift + } + settingDefinitionId = 'com.apple.managedclient.preferences_tags_item_value' + } + ) + } + ) + } + } + } + } + } + + 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-IntuneDeviceConfigurationPolicy -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope From edd3da8d5f50d2e3d404cffd10b591571eb36d2c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:04:46 +0000 Subject: [PATCH 17/23] Updated Resources and Cmdlet documentation pages --- ...EndpointDetectionAndResponsePolicyLinux.md | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyLinux.md diff --git a/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyLinux.md b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyLinux.md new file mode 100644 index 0000000000..dcce4db30c --- /dev/null +++ b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyLinux.md @@ -0,0 +1,188 @@ +# IntuneEndpointDetectionAndResponsePolicyLinux + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | Policy name | | +| **Description** | Write | String | Policy description | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **tags_item_value** | Write | String | Value of tag | | +| **tags_item_key** | Write | String | Type of tag (0: GROUP) | `0` | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + + +## Description + +Intune Endpoint Detection And Response Policy Linux + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My updated description' # Updated Property + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From 587cb28d90b58fd768c038c0d671634eccc18c58 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:07:25 +0000 Subject: [PATCH 18/23] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 5c9de6a8f1..106819cbc7 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -30149,6 +30149,86 @@ } ] }, + { + "ClassName": "MSFT_IntuneEndpointDetectionAndResponsePolicyLinux", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "tags_item_value", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "tags_item_key", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10", "Parameters": [ From d6360d0780f33d39a9f0f3855979a0e5fad14d98 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:08:41 +0000 Subject: [PATCH 19/23] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 1254e45f14..4bfd06a00c 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2209,6 +2209,19 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; } + IntuneEndpointDetectionAndResponsePolicyLinux 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + + } IntuneEndpointDetectionAndResponsePolicyWindows10 'myEDRPolicy' { DisplayName = 'Edr Policy' From d0f29d8969f104814b0b947de542587b5bf19e84 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:26:46 +0000 Subject: [PATCH 20/23] Updated Resources and Cmdlet documentation pages --- ...EndpointDetectionAndResponsePolicyMacOS.md | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyMacOS.md diff --git a/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyMacOS.md b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyMacOS.md new file mode 100644 index 0000000000..d7f9f57a4b --- /dev/null +++ b/docs/docs/resources/intune/IntuneEndpointDetectionAndResponsePolicyMacOS.md @@ -0,0 +1,188 @@ +# IntuneEndpointDetectionAndResponsePolicyMacOS + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **DisplayName** | Key | String | Policy name | | +| **Description** | Write | String | Policy description | | +| **RoleScopeTagIds** | Write | StringArray[] | List of Scope Tags for this Entity instance. | | +| **Id** | Write | String | The unique identifier for an entity. Read-only. | | +| **tags_item_value** | Write | String | Value of tag | | +| **tags_item_key** | Write | String | Type of tag (0: GROUP) | `0` | +| **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Represents the assignment to the Intune policy. | | +| **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **ApplicationSecret** | Write | PSCredential | Secret of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | +| **AccessTokens** | Write | StringArray[] | Access token used for authentication. | | + +### MSFT_DeviceManagementConfigurationPolicyAssignments + +#### Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **dataType** | Write | String | The type of the target assignment. | `#microsoft.graph.groupAssignmentTarget`, `#microsoft.graph.allLicensedUsersAssignmentTarget`, `#microsoft.graph.allDevicesAssignmentTarget`, `#microsoft.graph.exclusionGroupAssignmentTarget`, `#microsoft.graph.configurationManagerCollectionAssignmentTarget` | +| **deviceAndAppManagementAssignmentFilterType** | Write | String | The type of filter of the target assignment i.e. Exclude or Include. Possible values are:none, include, exclude. | `none`, `include`, `exclude` | +| **deviceAndAppManagementAssignmentFilterId** | Write | String | The Id of the filter for the target assignment. | | +| **groupId** | Write | String | The group Id that is the target of the assignment. | | +| **groupDisplayName** | Write | String | The group Display Name that is the target of the assignment. | | +| **collectionId** | Write | String | The collection Id that is the target of the assignment.(ConfigMgr) | | + + +## Description + +Intune Endpoint Detection And Response Policy MacOS + +## Permissions + +### Microsoft Graph + +To authenticate with the Microsoft Graph API, this resource required the following permissions: + +#### Delegated permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +#### Application permissions + +- **Read** + + - DeviceManagementConfiguration.Read.All + +- **Update** + + - DeviceManagementConfiguration.ReadWrite.All + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My updated description' # Updated Property + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + +### Example 3 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} +``` + From d27aff03af3ae331fc51dd7dec8003ea4a2e9e8a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 24 Jul 2024 15:27:14 -0400 Subject: [PATCH 21/23] Release 1.24.724.1 --- CHANGELOG.md | 8 ++-- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 49 +++++++------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5be0d9faed..39b9e762df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.724.1 * IntuneAntivirusPolicyWindows10SettingCatalog * Migrate to new settings catalog cmdlets. @@ -12,9 +12,9 @@ * IntuneEndointDetectionAndResponsePolicyMacOS * Initial release. * IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 - * Introduces new properties and updates the handling of the - start and end dates. - FIXES [#4614](https://github.com/microsoft/Microsoft365DSC/issues/4614) + * Introduces new properties and updates the handling of the + start and end dates. + FIXES [#4614](https://github.com/microsoft/Microsoft365DSC/issues/4614) FIXES [#3438](https://github.com/microsoft/Microsoft365DSC/issues/3438) * M365DSCDRGUtil * Fixes an issue where only 25 settings catalog templates were fetched with one call. diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index ef6275d857..b3072f2289 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-07-17 +# Generated on: 2024-07-24 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.717.1' + ModuleVersion = '1.24.724.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -142,37 +142,24 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* EXOHostedOutboundSpamFilterPolicy - * Changed the RecipientLimitInternalPerHour, RecipientLimitPerDay, and - RecipientLimitExternalPerHour parameters to UInt32. -* EXOMessageClassification - * Fix issue while creating policy for first time - FIXES [#4877](https://github.com/microsoft/Microsoft365DSC/issues/4877) -* IntuneDeviceConfigurationEmailProfilePolicyWindows10 - * Fix export by fixing some typos and from where values are extracted - FIXES [#3960](https://github.com/microsoft/Microsoft365DSC/issues/3960) -* IntuneDiskEncryptionWindows10 - * Initial Release - FIXES [#4050](https://github.com/microsoft/Microsoft365DSC/issues/4050) -* IntuneWindowsUpdateForBusinessQualityUpdateProfileWindows10 + ReleaseNotes = '* IntuneAntivirusPolicyWindows10SettingCatalog + * Migrate to new settings catalog cmdlets. +* IntuneAttackSurfaceReductionRulesPolicyWindows10ConfigManager + * Migrate to new settings catalog cmdlets. + FIXES [#3966](https://github.com/microsoft/Microsoft365DSC/issues/3966) +* IntuneEndpointDetectionAndResponsePolicyLinux * Initial release. - FIXES [#2659](https://github.com/microsoft/Microsoft365DSC/issues/2659) -* SPOSharingSettings - * Improved performance by using -Filter on Get-PnPTenantSite calls. +* IntuneEndointDetectionAndResponsePolicyMacOS + * Initial release. +* IntuneWindowsUpdateForBusinessFeatureUpdateProfileWindows10 + * Introduces new properties and updates the handling of the + start and end dates. + FIXES [#4614](https://github.com/microsoft/Microsoft365DSC/issues/4614) + FIXES [#3438](https://github.com/microsoft/Microsoft365DSC/issues/3438) * M365DSCDRGUtil - * Fixes an issue with nested and duplicate settings in the settings catalog - * Add support for converting Intune assignments directly from Graph. - FIXES [#4875](https://github.com/microsoft/Microsoft365DSC/issues/4875) -* M365DSCResourceGenerator - * Update Intune resource generation. -* M365DSCReport - * Changes behaviour to not throw on empty configuration during report generation. - FIXES [#4559](https://github.com/microsoft/Microsoft365DSC/issues/4559) - FIXES [#4505](https://github.com/microsoft/Microsoft365DSC/issues/4505) - * Fixes an issue where the comparison treats empty arrays as an empty string. - FIXES [#4796](https://github.com/microsoft/Microsoft365DSC/issues/4796) -* Telemetry - * Added info about operation total execution time.' + * Fixes an issue where only 25 settings catalog templates were fetched with one call. +* SPOSharingSettings + * Changed approach to MySite filtering.' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 71ca876dae11efad835f8a844ffb930670e96a8c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:28:57 +0000 Subject: [PATCH 22/23] Updated {Create} Intune Integration Tests --- .../M365DSCIntegration.INTUNE.Create.Tests.ps1 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 index 4bfd06a00c..375dd122e6 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.INTUNE.Create.Tests.ps1 @@ -2221,6 +2221,19 @@ TenantId = $TenantId; CertificateThumbprint = $CertificateThumbprint; + } + IntuneEndpointDetectionAndResponsePolicyMacOS 'myEDRPolicy' + { + DisplayName = 'Edr Policy' + tags_item_key = '0' + tags_item_value = 'tag' + Assignments = @() + Description = 'My revised description' + Ensure = 'Present' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } IntuneEndpointDetectionAndResponsePolicyWindows10 'myEDRPolicy' { From e79657a96305cc1592bcaa40133d80c5a35007f5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 24 Jul 2024 19:45:41 +0000 Subject: [PATCH 23/23] Updated Schema Definition --- Modules/Microsoft365DSC/SchemaDefinition.json | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/Modules/Microsoft365DSC/SchemaDefinition.json b/Modules/Microsoft365DSC/SchemaDefinition.json index 106819cbc7..25293aadb8 100644 --- a/Modules/Microsoft365DSC/SchemaDefinition.json +++ b/Modules/Microsoft365DSC/SchemaDefinition.json @@ -30229,6 +30229,86 @@ } ] }, + { + "ClassName": "MSFT_IntuneEndpointDetectionAndResponsePolicyMacOS", + "Parameters": [ + { + "CIMType": "String", + "Name": "DisplayName", + "Option": "Key" + }, + { + "CIMType": "String", + "Name": "Description", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "RoleScopeTagIds", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "Id", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "tags_item_value", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "tags_item_key", + "Option": "Write" + }, + { + "CIMType": "MSFT_DeviceManagementConfigurationPolicyAssignments[]", + "Name": "Assignments", + "Option": "Write" + }, + { + "CIMType": "string", + "Name": "Ensure", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "Credential", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "ApplicationId", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "TenantId", + "Option": "Write" + }, + { + "CIMType": "MSFT_Credential", + "Name": "ApplicationSecret", + "Option": "Write" + }, + { + "CIMType": "String", + "Name": "CertificateThumbprint", + "Option": "Write" + }, + { + "CIMType": "Boolean", + "Name": "ManagedIdentity", + "Option": "Write" + }, + { + "CIMType": "String[]", + "Name": "AccessTokens", + "Option": "Write" + } + ] + }, { "ClassName": "MSFT_IntuneEndpointDetectionAndResponsePolicyWindows10", "Parameters": [