diff --git a/CHANGELOG.md b/CHANGELOG.md index f8af9c4cda..058484508c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,8 @@ * IntuneAccountProtectionLocalUserGroupMembershipPolicy * Updates values in `UserSelectionType`. FIXES [#5318](https://github.com/microsoft/Microsoft365DSC/issues/5318) +* IntuneAntivirusPolicyLinux + * Initial release. * IntuneAppAndBrowserIsolationPolicyWindows10ConfigMgr * Initial release. * IntuneAppCategory diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.psm1 new file mode 100644 index 0000000000..46e096cf71 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.psm1 @@ -0,0 +1,1013 @@ +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()] + [ValidateSet('false', 'true')] + [System.String] + $enabled, + + [Parameter()] + [ValidateSet('none', 'safe', 'all')] + [System.String] + $automaticSampleSubmissionConsent, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $diagnosticLevel, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $automaticDefinitionUpdateEnabled, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableRealTimeProtection, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $passiveMode, + + [Parameter()] + [ValidateRange(5000, 15000)] + [System.Int32] + $scanHistoryMaximumItems, + + [Parameter()] + [ValidateRange(1, 180)] + [System.Int32] + $scanResultsRetentionDays, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $exclusionsMergePolicy, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $exclusions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $threatTypeSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $threatTypeSettingsMergePolicy, + + [Parameter()] + [System.String[]] + $allowedThreats, + + [Parameter()] + [System.String[]] + $disallowedThreatActions, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanArchives, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanAfterDefinitionUpdate, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableFileHashComputation, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $behaviorMonitoring, + + [Parameter()] + [ValidateSet('normal', 'moderate', 'high', 'plus', 'tolerance')] + [System.String] + $cloudBlockLevel, + + [Parameter()] + [ValidateRange(1, 64)] + [System.Int32] + $maximumOnDemandScanThreads, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $networkprotection_enforcementLevel, + + [Parameter()] + [System.String[]] + $unmonitoredFilesystems, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $nonExecMountPolicy, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $antivirusengine_enforcementLevel, + + [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 Antivirus 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 Antivirus Policy Linux with Name {$DisplayName}." + return $nullResult + } + $Id = $getValue.Id + Write-Verbose -Message "An Intune Antivirus Policy Linux with Id {$Id} and Name {$DisplayName} was found" + + # Retrieve policy specific settings + [array]$settings = Get-MgBetaDeviceManagementConfigurationPolicySetting ` + -DeviceManagementConfigurationPolicyId $Id ` + -ExpandProperty 'settingDefinitions' ` + -All ` + -ErrorAction Stop + $policyTemplateId = $getValue.TemplateReference.TemplateId + [array]$settingDefinitions = Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate ` + -DeviceManagementConfigurationPolicyTemplateId $policyTemplateId ` + -ExpandProperty 'settingDefinitions' ` + -All ` + -ErrorAction Stop | Select-Object -ExpandProperty SettingDefinitions + + $policySettings = @{} + $policySettings = Export-IntuneSettingCatalogPolicySettings -Settings $settings -ReturnHashtable $policySettings -AllSettingDefinitions $settingDefinitions + + #region resource generator code + $complexExclusions = @() + foreach ($currentExclusions in $policySettings.exclusions) + { + $myExclusions = @{} + $myExclusions.Add('Exclusions_item_type', $currentExclusions.exclusions_item_type) + $myExclusions.Add('Exclusions_item_extension', $currentExclusions.exclusions_item_extension) + $myExclusions.Add('Exclusions_item_name', $currentExclusions.exclusions_item_name) + $myExclusions.Add('Exclusions_item_path', $currentExclusions.exclusions_item_path) + $myExclusions.Add('Exclusions_item_isDirectory', $currentExclusions.exclusions_item_isDirectory) + if ($myExclusions.values.Where({$null -ne $_}).Count -gt 0) + { + $complexExclusions += $myExclusions + } + } + $policySettings.Remove('exclusions') | Out-Null + + $complexThreatTypeSettings = @() + foreach ($currentThreatTypeSettings in $policySettings.threatTypeSettings) + { + $myThreatTypeSettings = @{} + $myThreatTypeSettings.Add('ThreatTypeSettings_item_key', $currentThreatTypeSettings.threatTypeSettings_item_key) + $myThreatTypeSettings.Add('ThreatTypeSettings_item_value', $currentThreatTypeSettings.threatTypeSettings_item_value) + if ($myThreatTypeSettings.values.Where({$null -ne $_}).Count -gt 0) + { + $complexThreatTypeSettings += $myThreatTypeSettings + } + } + $policySettings.Remove('threatTypeSettings') | Out-Null + #endregion + + $results = @{ + #region resource generator code + Description = $getValue.Description + DisplayName = $getValue.Name + RoleScopeTagIds = $getValue.RoleScopeTagIds + Id = $getValue.Id + exclusions = $complexExclusions + threatTypeSettings = $complexThreatTypeSettings + 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()] + [ValidateSet('false', 'true')] + [System.String] + $enabled, + + [Parameter()] + [ValidateSet('none', 'safe', 'all')] + [System.String] + $automaticSampleSubmissionConsent, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $diagnosticLevel, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $automaticDefinitionUpdateEnabled, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableRealTimeProtection, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $passiveMode, + + [Parameter()] + [ValidateRange(5000, 15000)] + [System.Int32] + $scanHistoryMaximumItems, + + [Parameter()] + [ValidateRange(1, 180)] + [System.Int32] + $scanResultsRetentionDays, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $exclusionsMergePolicy, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $exclusions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $threatTypeSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $threatTypeSettingsMergePolicy, + + [Parameter()] + [System.String[]] + $allowedThreats, + + [Parameter()] + [System.String[]] + $disallowedThreatActions, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanArchives, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanAfterDefinitionUpdate, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableFileHashComputation, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $behaviorMonitoring, + + [Parameter()] + [ValidateSet('normal', 'moderate', 'high', 'plus', 'tolerance')] + [System.String] + $cloudBlockLevel, + + [Parameter()] + [ValidateRange(1, 64)] + [System.Int32] + $maximumOnDemandScanThreads, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $networkprotection_enforcementLevel, + + [Parameter()] + [System.String[]] + $unmonitoredFilesystems, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $nonExecMountPolicy, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $antivirusengine_enforcementLevel, + + [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 = '4cfd164c-5e8a-4ea9-b15d-9aa71e4ffff4_1' + $platforms = 'linux' + $technologies = 'microsoftSense' + + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating an Intune Antivirus 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 Antivirus 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 Antivirus 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()] + [ValidateSet('false', 'true')] + [System.String] + $enabled, + + [Parameter()] + [ValidateSet('none', 'safe', 'all')] + [System.String] + $automaticSampleSubmissionConsent, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $diagnosticLevel, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $automaticDefinitionUpdateEnabled, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableRealTimeProtection, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $passiveMode, + + [Parameter()] + [ValidateRange(5000, 15000)] + [System.Int32] + $scanHistoryMaximumItems, + + [Parameter()] + [ValidateRange(1, 180)] + [System.Int32] + $scanResultsRetentionDays, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $exclusionsMergePolicy, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $exclusions, + + [Parameter()] + [Microsoft.Management.Infrastructure.CimInstance[]] + $threatTypeSettings, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $threatTypeSettingsMergePolicy, + + [Parameter()] + [System.String[]] + $allowedThreats, + + [Parameter()] + [System.String[]] + $disallowedThreatActions, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanArchives, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $scanAfterDefinitionUpdate, + + [Parameter()] + [ValidateSet('false', 'true')] + [System.String] + $enableFileHashComputation, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $behaviorMonitoring, + + [Parameter()] + [ValidateSet('normal', 'moderate', 'high', 'plus', 'tolerance')] + [System.String] + $cloudBlockLevel, + + [Parameter()] + [ValidateRange(1, 64)] + [System.Int32] + $maximumOnDemandScanThreads, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $networkprotection_enforcementLevel, + + [Parameter()] + [System.String[]] + $unmonitoredFilesystems, + + [Parameter()] + [ValidateSet('0', '1')] + [System.String] + $nonExecMountPolicy, + + [Parameter()] + [ValidateSet('0', '1', '2')] + [System.String] + $antivirusengine_enforcementLevel, + + [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 Antivirus 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 = "4cfd164c-5e8a-4ea9-b15d-9aa71e4ffff4_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 ($null -ne $Results.exclusions) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.exclusions ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogExclusions' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.exclusions = $complexTypeStringResult + } + else + { + $Results.Remove('exclusions') | Out-Null + } + } + if ($null -ne $Results.threatTypeSettings) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.threatTypeSettings ` + -CIMInstanceName 'MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings' + if (-not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.threatTypeSettings = $complexTypeStringResult + } + else + { + $Results.Remove('threatTypeSettings') | Out-Null + } + } + + if ($Results.Assignments) + { + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString -ComplexObject $Results.Assignments -CIMInstanceName DeviceManagementConfigurationPolicyAssignments + if ($complexTypeStringResult) + { + $Results.Assignments = $complexTypeStringResult + } + else + { + $Results.Remove('Assignments') | Out-Null + } + } + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.exclusions) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "exclusions" -IsCIMArray:$True + } + if ($Results.threatTypeSettings) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "threatTypeSettings" -IsCIMArray:$True + } + + if ($Results.Assignments) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "Assignments" -IsCIMArray:$true + } + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.schema.mof new file mode 100644 index 0000000000..949abac55d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/MSFT_IntuneAntivirusPolicyLinux.schema.mof @@ -0,0 +1,69 @@ +[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")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions +{ + [Write, Description("Type - Depends on exclusions (0: Path, 1: File extension, 2: Process name)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String exclusions_item_type; + [Write, Description("File extension - Depends on exclusions_item_type=1")] String exclusions_item_extension; + [Write, Description("File name - exclusions_item_type=2")] String exclusions_item_name; + [Write, Description("Path - exclusions_item_type=0")] String exclusions_item_path; + [Write, Description("Is directory (false: Disabled, true: Enabled) - Depends on exclusions_item_type=0"), ValueMap{"false", "true"}, Values{"false", "true"}] String exclusions_item_isDirectory; +}; + +[ClassVersion("1.0.0.0")] +class MSFT_MicrosoftGraphIntuneSettingsCatalogthreatTypeSettings +{ + [Write, Description("Threat type - Depends on threatTypeSettings (0: potentially_unwanted_application, 1: archive_bomb)"), ValueMap{"0", "1"}, Values{"0", "1"}] String threatTypeSettings_item_key; + [Write, Description("Action to take - Depends on threatTypeSettings (0: audit, 1: block, 2: off)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String threatTypeSettings_item_value; +}; + +[ClassVersion("1.0.0.0"), FriendlyName("IntuneAntivirusPolicyLinux")] +class MSFT_IntuneAntivirusPolicyLinux : OMI_BaseResource +{ + [Write, Description("Policy description")] String Description; + [Key, Description("Policy name")] String DisplayName; + [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("Enable cloud delivered protection (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String enabled; + [Write, Description("Enable automatic sample submissions (none: None, safe: Safe, all: All)"), ValueMap{"none", "safe", "all"}, Values{"none", "safe", "all"}] String automaticSampleSubmissionConsent; + [Write, Description("Diagnostic data collection level (0: optional, 1: required)"), ValueMap{"0", "1"}, Values{"0", "1"}] String diagnosticLevel; + [Write, Description("Automatic security intelligence updates (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String automaticDefinitionUpdateEnabled; + [Write, Description("Enable real-time protection (deprecated) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String enableRealTimeProtection; + [Write, Description("Enable passive mode (deprecated) (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String passiveMode; + [Write, Description("Scan history size")] SInt32 scanHistoryMaximumItems; + [Write, Description("Scan results retention")] SInt32 scanResultsRetentionDays; + [Write, Description("Exclusions merge (0: merge, 1: admin_only)"), ValueMap{"0", "1"}, Values{"0", "1"}] String exclusionsMergePolicy; + [Write, Description("Scan exclusions"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions")] String exclusions[]; + [Write, Description("Threat type settings"), EmbeddedInstance("MSFT_MicrosoftGraphIntuneSettingsCatalogthreatTypeSettings")] String threatTypeSettings[]; + [Write, Description("Threat type settings merge (0: merge, 1: admin_only)"), ValueMap{"0", "1"}, Values{"0", "1"}] String threatTypeSettingsMergePolicy; + [Write, Description("Allowed threats")] String allowedThreats[]; + [Write, Description("Disallowed threat actions")] String disallowedThreatActions[]; + [Write, Description("Enable scanning of archives (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String scanArchives; + [Write, Description("Enable scanning after definition update (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String scanAfterDefinitionUpdate; + [Write, Description("Enable file hash computation (false: Disabled, true: Enabled)"), ValueMap{"false", "true"}, Values{"false", "true"}] String enableFileHashComputation; + [Write, Description("Enable behavior monitoring (0: Disabled, 1: Enabled)"), ValueMap{"0", "1"}, Values{"0", "1"}] String behaviorMonitoring; + [Write, Description("Configure cloud block level (normal: Normal, moderate: Moderate, high: High, plus: High_Plus, tolerance: Zero_Tolerance)"), ValueMap{"normal", "moderate", "high", "plus", "tolerance"}, Values{"normal", "moderate", "high", "plus", "tolerance"}] String cloudBlockLevel; + [Write, Description("maximum on demand scan threads")] SInt32 maximumOnDemandScanThreads; + [Write, Description("Enforcement Level (0: disabled, 1: audit, 2: block)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String networkprotection_enforcementLevel; + [Write, Description("Unmonitored Filesystems")] String unmonitoredFilesystems[]; + [Write, Description("non execute mount mute (0: unmute, 1: mute)"), ValueMap{"0", "1"}, Values{"0", "1"}] String nonExecMountPolicy; + [Write, Description("Enforcement Level (0: Realtime, 1: OnDemand, 2: Passive)"), ValueMap{"0", "1", "2"}, Values{"0", "1", "2"}] String antivirusengine_enforcementLevel; + [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_IntuneAntivirusPolicyLinux/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/readme.md new file mode 100644 index 0000000000..d8060ea61a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/readme.md @@ -0,0 +1,6 @@ + +# IntuneAntivirusPolicyLinux + +## Description + +Intune Antivirus Policy Linux diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/settings.json new file mode 100644 index 0000000000..996c1ddb08 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAntivirusPolicyLinux/settings.json @@ -0,0 +1,45 @@ +{ + "resourceName": "IntuneAntivirusPolicyLinux", + "description": "This resource configures an Intune Antivirus Policy Linux.", + "permissions": { + "graph": { + "delegated": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + }, + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + }, + { + "name": "Group.Read.All" + } + ] + }, + "application": { + "read": [ + { + "name": "DeviceManagementConfiguration.Read.All" + }, + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "DeviceManagementConfiguration.ReadWrite.All" + }, + { + "name": "Group.Read.All" + } + ] + } + } +} + +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/1-Create.ps1 new file mode 100644 index 0000000000..bc609219f1 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/1-Create.ps1 @@ -0,0 +1,61 @@ +<# +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 + { + IntuneAntivirusPolicyLinux 'myIntuneAntivirusPolicyLinux' + { + allowedThreats = @("Threat 1"); + Assignments = @(); + Description = ""; + disallowedThreatActions = @("Disallowed Thread Action 1"); + DisplayName = "Test"; + enabled = "true"; + Ensure = "Present"; + exclusions = @( + MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions{ + Exclusions_item_extension = '.exe' + Exclusions_item_type = '1' + } + MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions{ + Exclusions_item_name = 'process1' + Exclusions_item_type = '2' + } + ); + RoleScopeTagIds = @("0"); + threatTypeSettings = @( + MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } + MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings{ + ThreatTypeSettings_item_key = '1' + ThreatTypeSettings_item_value = '1' + } + ); + unmonitoredFilesystems = @("Filesystem 1"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/2-Update.ps1 new file mode 100644 index 0000000000..16a971c59b --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/2-Update.ps1 @@ -0,0 +1,61 @@ +<# +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 + { + IntuneAntivirusPolicyLinux 'myIntuneAntivirusPolicyLinux' + { + allowedThreats = @("Threat 1"); + Assignments = @(); + Description = ""; + disallowedThreatActions = @("Disallowed Thread Action 1"); + DisplayName = "Test"; + enabled = "true"; + Ensure = "Present"; + exclusions = @( + MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions{ + Exclusions_item_extension = '.vba' # Updated property + Exclusions_item_type = '1' + } + MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions{ + Exclusions_item_name = 'process1' + Exclusions_item_type = '2' + } + ); + RoleScopeTagIds = @("0"); + threatTypeSettings = @( + MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } + MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings{ + ThreatTypeSettings_item_key = '1' + ThreatTypeSettings_item_value = '1' + } + ); + unmonitoredFilesystems = @("Filesystem 1"); + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/3-Remove.ps1 new file mode 100644 index 0000000000..0324ea22b3 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/IntuneAntivirusPolicyLinux/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 + { + IntuneAntivirusPolicyLinux 'myIntuneAntivirusPolicyLinux' + { + DisplayName = 'test' + Ensure = 'Absent' + ApplicationId = $ApplicationId; + TenantId = $TenantId; + CertificateThumbprint = $CertificateThumbprint; + } + } +} diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 13e85501ce..c6ac727450 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1665,8 +1665,16 @@ function Get-IntuneSettingCatalogPolicySetting { $settingValueType = $settingValueType.Replace('ValueTemplate', 'Value') } + $settingValueTemplateId = $settingInstanceTemplate.AdditionalProperties."$($settingValueName)Template".settingValueTemplateId + # Only happened on property ThreatTypeSettings from IntuneAntivirusPolicyLinux + # SettingValueTemplateIds are from the child settings and not from the parent setting because it is a groupSettingCollection + if ($settingValueTemplateId -is [array]) + { + $settingValueTemplateId = $null + } + # Get all the values in the setting instance $settingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` -DSCParams $DSCParams ` @@ -1766,8 +1774,8 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue } $instanceCount = 1 - if (($Level -ge 2 -and $groupSettingCollectionDefinitionChildren.Count -gt 1) -or - ($Level -eq 1 -and $groupSettingCollectionDefinitionChildren.Count -gt 1 -and $SettingDefinition.AdditionalProperties.maximumCount -gt 1)) + if (($Level -gt 1 -and $groupSettingCollectionDefinitionChildren.Count -gt 1) -or + ($Level -eq 1 -and $groupSettingCollectionDefinitionChildren.Count -ge 1 -and $groupSettingCollectionDefinitionChildren.AdditionalProperties.'@odata.type' -notcontains "#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition")) { $SettingInstanceName += Get-SettingsCatalogSettingName -SettingDefinition $SettingDefinition -AllSettingDefinitions $AllSettingDefinitions $cimDSCParams = @() @@ -1785,7 +1793,10 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue $newInstanceDSCParams = @{} # Preserve CIM instances when converting to hashtable foreach ($property in $instance.CimInstanceProperties) { - $newInstanceDSCParams.Add($property.Name, $property.Value) + if ($property.IsValueModified) + { + $newInstanceDSCParams.Add($property.Name, $property.Value) + } } $newDSCParams.$cimDSCParamsName += $newInstanceDSCParams } @@ -1824,12 +1835,14 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue $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 ) - $childSettingInstanceTemplate = if ($null -ne $SettingInstanceTemplate.AdditionalProperties) { - $SettingInstanceTemplate.AdditionalProperties.groupSettingCollectionValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } + $childSettingInstanceTemplate = if ($null -ne $SettingInstanceTemplate.AdditionalProperties) { + $SettingInstanceTemplate.AdditionalProperties.groupSettingCollectionValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } | Select-Object -First 1 } else { - $SettingInstanceTemplate.groupSettingCollectionValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } + $SettingInstanceTemplate.groupSettingCollectionValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } | Select-Object -First 1 } + $childSettingValueTemplateId = $childSettingInstanceTemplate."$($childSettingValueName)Template".settingValueTemplateId + $childSettingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` -DSCParams $currentDSCParams ` -SettingDefinition $childDefinition ` @@ -1868,12 +1881,14 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue ) settingDefinitionId = $childDefinition.Id } + <# GroupSettingCollection do not have a setting instance template reference if (-not [string]::IsNullOrEmpty($childSettingInstanceTemplate.settingInstanceTemplateId)) { $childSettingValueInner.children[0].groupSettingCollectionValue.settingInstanceTemplateReference = @{ 'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId } } + #> $childSettingValue += $childSettingValueInner } $groupSettingCollectionValue += $childSettingValue @@ -1884,10 +1899,12 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue { $childSettingValue.Add('settingDefinitionId', $childDefinition.Id) } + <# GroupSettingCollection do not have a setting instance template reference if (-not [string]::IsNullOrEmpty($childSettingInstanceTemplate.settingInstanceTemplateId)) { - $childSettingValue.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId }) + $childSettingValue.Add('settingInstanceTemplateReference', @{'settingInstanceTemplateId' = $childSettingInstanceTemplate.settingInstanceTemplateId | Select-Object -First 1 }) } + #> $childSettingValue.Add('@odata.type', $childSettingType) $groupSettingCollectionValueChildren += $childSettingValue } @@ -1922,30 +1939,31 @@ function Get-IntuneSettingCatalogPolicySettingInstanceValue ($_.AdditionalProperties.options.dependentOn.Count -gt 0 -and $_.AdditionalProperties.options.dependentOn.parentSettingId.Contains($SettingDefinition.Id)) } } - if ($CurrentInstanceDefinitions.Count -eq 5) - { - Write-Host "blub" - } + foreach ($childDefinition in $choiceSettingDefinitionChildren) { $childSettingType = $childDefinition.AdditionalProperties.'@odata.type'.Replace('Definition', '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 ) - <# There are no child instance templates under a choice setting instance - $childSettingInstanceTemplate = $SettingTemplates.SettingInstanceTemplate | Where-Object { $_.SettingDefinitionId -eq $childDefinition.Id } - $childSettingValueTemplateId = $childSettingInstanceTemplate.AdditionalProperties."$($childSettingValueName)Template".settingValueTemplateId - #> + $childSettingInstanceTemplate = if ($null -ne $SettingInstanceTemplate.AdditionalProperties) { + $SettingInstanceTemplate.AdditionalProperties.choiceSettingValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } + } else { + $SettingInstanceTemplate.choiceSettingValueTemplate.children | Where-Object { $_.settingDefinitionId -eq $childDefinition.Id } + } + $childSettingValueTemplateId = $childSettingInstanceTemplate."$($childSettingValueName)Template" | Where-Object { + $_.settingDefinitionId -eq $childDefinition.Id + } | Select-Object -ExpandProperty settingValueTemplateId $childSettingValue = Get-IntuneSettingCatalogPolicySettingInstanceValue ` -DSCParams $DSCParams ` -SettingDefinition $childDefinition ` -AllSettingDefinitions $AllSettingDefinitions ` -CurrentInstanceDefinitions $CurrentInstanceDefinitions ` - -SettingInstanceTemplate $SettingInstanceTemplate ` + -SettingInstanceTemplate $childSettingInstanceTemplate ` -SettingType $childDefinition.AdditionalProperties.'@odata.type' ` -SettingValueName $childSettingValueName ` -SettingValueType $childSettingValueType ` - -SettingValueTemplateId $null ` + -SettingValueTemplateId $childSettingValueTemplateId ` -SettingInstanceName $SettingInstanceName if ($childSettingValue.Keys.Count -gt 0) @@ -2206,6 +2224,9 @@ function Export-IntuneSettingCatalogPolicySettings Mandatory = $true, ParameterSetName = 'Setting' )] + [Parameter( + ParameterSetName = 'Start' + )] [System.Array] $AllSettingDefinitions, @@ -2228,18 +2249,39 @@ function Export-IntuneSettingCatalogPolicySettings $deviceSettings = $Settings | Where-Object -FilterScript { $_.SettingInstance.settingDefinitionId.StartsWith("device_") } + if ($AllSettingDefinitions.Count -eq 0) + { + $allDeviceSettingDefinitions = $deviceSettings.SettingDefinitions + } + else + { + $allDeviceSettingDefinitions = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id.StartsWith("device_") + } + } foreach ($setting in $deviceSettings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $deviceSettingsReturnHashtable -AllSettingDefinitions $deviceSettings.SettingDefinitions -IsRoot + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $deviceSettingsReturnHashtable -AllSettingDefinitions $allDeviceSettingDefinitions -IsRoot } + $userSettingsReturnHashtable = @{} $userSettings = $Settings | Where-Object -FilterScript { $_.SettingInstance.settingDefinitionId.StartsWith("user_") } - $userSettingsReturnHashtable = @{} + if ($AllSettingDefinitions.Count -eq 0) + { + $allUserSettingDefinitions = $userSettings.SettingDefinitions + } + else + { + $allUserSettingDefinitions = $AllSettingDefinitions | Where-Object -FilterScript { + $_.Id.StartsWith("user_") + } + } + foreach ($setting in $userSettings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $userSettingsReturnHashtable -AllSettingDefinitions $userSettings.SettingDefinitions -IsRoot + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $userSettingsReturnHashtable -AllSettingDefinitions $allUserSettingDefinitions -IsRoot } if ($deviceSettingsReturnHashtable.Keys.Count -gt 0) @@ -2253,9 +2295,13 @@ function Export-IntuneSettingCatalogPolicySettings } else { + if ($AllSettingDefinitions.Count -eq 0) + { + $AllSettingDefinitions = $Settings.SettingDefinitions + } foreach ($setting in $Settings) { - Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $Settings.SettingDefinitions -IsRoot + Export-IntuneSettingCatalogPolicySettings -SettingInstance $setting.SettingInstance -SettingDefinitions $setting.SettingDefinitions -ReturnHashtable $ReturnHashtable -AllSettingDefinitions $AllSettingDefinitions -IsRoot } } return $ReturnHashtable @@ -2294,9 +2340,10 @@ function Export-IntuneSettingCatalogPolicySettings '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' { $groupSettingCollectionValue = if ($IsRoot) { $SettingInstance.AdditionalProperties.groupSettingCollectionValue } else { $SettingInstance.groupSettingCollectionValue } - $childSettingDefinitions = $SettingDefinitions | Where-Object -FilterScript { + [array]$childSettingDefinitions = $SettingDefinitions | Where-Object -FilterScript { $settingDefinition.AdditionalProperties.childIds -contains $_.Id } + $parentSettingDefinition = $SettingDefinitions | Where-Object -FilterScript { $_.Id -eq $settingDefinition.AdditionalProperties.dependentOn.parentSettingId } if ($settingDefinition.AdditionalProperties.maximumCount -gt 1 -and $childSettingDefinitions.Count -eq 1) { @@ -2311,15 +2358,28 @@ function Export-IntuneSettingCatalogPolicySettings } $addToParameters = $false } - elseif (-not $IsRoot -and $childSettingDefinitions.Count -gt 1) + elseif (($settingDefinition.AdditionalProperties.maximumCount -gt 1 -or $parentSettingDefinition.AdditionalProperties.maximumCount -gt 1) -and $childSettingDefinitions.Count -gt 1) { + # If the GroupSettingCollection can appear multiple times (either itself or from the parent), we need to add its name as a property + # and the child settings as its value $childValue = $null - $parentSettingDefinition = $SettingDefinitions | Where-Object -FilterScript { $_.Id -eq $settingDefinition.AdditionalProperties.dependentOn.parentSettingId } - if ($settingDefinition.AdditionalProperties.maximumCount -gt 1 -or - $parentSettingDefinition.AdditionalProperties.maximumCount -gt 1) + if (-not $IsRoot) + { + $parentSettingDefinition = $SettingDefinitions | Where-Object -FilterScript { $_.Id -eq $settingDefinition.AdditionalProperties.dependentOn.parentSettingId } + if ($settingDefinition.AdditionalProperties.maximumCount -gt 1 -or + $parentSettingDefinition.AdditionalProperties.maximumCount -gt 1) + { + $childValue = @() + } + } + else { - $childValue = @() + if ($settingDefinition.AdditionalProperties.maximumCount -gt 1) + { + $childValue = @() + } } + foreach ($child in $groupSettingCollectionValue) { $childHashtable = @{} @@ -2333,6 +2393,7 @@ function Export-IntuneSettingCatalogPolicySettings } else { + # Skip GroupSettingCollection that only appears once, go straight to the child properties $childSettings = $groupSettingCollectionValue.children foreach ($value in $childSettings) { @@ -2409,7 +2470,7 @@ function Update-IntuneDeviceConfigurationPolicy try { $Uri = $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.ResourceUrl + "beta/deviceManagement/configurationPolicies/$DeviceConfigurationPolicyId" - + $policy = @{ 'name' = $Name 'description' = $Description diff --git a/Modules/Microsoft365DSC/Modules/M365DSCIntuneSettingsCatalogUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCIntuneSettingsCatalogUtil.psm1 index b8da1eb8fb..65613fd700 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCIntuneSettingsCatalogUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCIntuneSettingsCatalogUtil.psm1 @@ -50,38 +50,10 @@ # If the combination of parent setting and setting name is still not unique, do it with the OffsetUri of the current setting else { - $skip = 0 - $breakCounter = 0 - $newSettingName = $settingName - do { - $previousSettingName = $newSettingName - $newSettingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $newSettingName -Skip $skip - - $combinationMatchesWithOffsetUri = @() - $settingsWithSameName | ForEach-Object { - $newName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip - if ($newName -eq $newSettingName) - { - # Exclude v2 versions from the comparison - if ($SettingDefinition.Id -like "*_v2" -and $_.Id -ne $SettingDefinition.Id.Replace('_v2', '') -or - $SettingDefinition.Id -notlike "*_v2" -and $_.Id -ne $SettingDefinition.Id + "_v2") - { - $combinationMatchesWithOffsetUri += $_ - } - } - } - $settingsWithSameName = $combinationMatchesWithOffsetUri - $skip++ - $breakCounter++ - } while ($combinationMatchesWithOffsetUri.Count -gt 1 -and $breakCounter -lt 8) - - if ($breakCounter -lt 8) + $settingResult = Get-UniqueSettingDefinitionNameFromMultipleMatches -SettingDefinition $SettingDefinition -SettingName $settingName -SettingsWithSameName $settingsWithSameName + if ($settingResult.Success) { - if ($SettingDefinition.Id -like "*_v2" -and $newSettingName -notlike "*_v2") - { - $newSettingName += "_v2" - } - $settingName = $newSettingName + $settingName = $settingResult.SettingName } else { @@ -89,18 +61,28 @@ $parentSettingIdProperty = $parentSetting.Id.Split('_')[-1] $parentSettingIdWithoutProperty = $parentSetting.Id.Replace("_$parentSettingIdProperty", "") # We can't use the entire setting here, because the child setting id does not have to come after the parent setting id - $settingName = $settingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") + $settingName = $SettingDefinition.Id.Replace($parentSettingIdWithoutProperty + "_", "").Replace($parentSettingIdProperty + "_", "") } } } # When there is no parent, we can't use the parent setting name to make the setting name unique - # Instead, we traverse up the OffsetUri. Since no parent setting can only happen at the root level, the result - # of Get-SettingDefinitionNameWithParentFromOffsetUri is absolute and cannot change. There cannot be multiple settings with the same name - # in the same level of OffsetUri + # Instead, we traverse up the OffsetUri. if ($null -eq $parentSetting) { - $settingName = Get-SettingDefinitionNameWithParentFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $settingName + $settingResult = Get-UniqueSettingDefinitionNameFromMultipleMatches -SettingDefinition $SettingDefinition -SettingName $settingName -SettingsWithSameName $settingsWithSameName + if ($settingResult.Success) + { + $settingName = $settingResult.SettingName + } + else + { + # Can happen if both settings have the same name and the same OffsetUri, e.g. "enforcementLevel" in the IntuneAntivirusPolicyLinux resource + # Potential risk of overwriting settings with the same name but different OffsetUri + $settingIdWithoutName = $SettingDefinition.Id -replace "_$settingName", "" + $settingIdWithoutNameSplitted = $settingIdWithoutName.Split("_")[-1] + $settingName = $settingIdWithoutNameSplitted + "_" + $settingName + } } # Simplify names from the OffsetUri. This is done to make the names more readable, especially in case of long and complex OffsetUris. @@ -153,7 +135,64 @@ function Get-ParentSettingDefinition { $parentSetting } -function Get-SettingDefinitionNameWithParentFromOffsetUri { +function Get-UniqueSettingDefinitionNameFromMultipleMatches { + param ( + [Parameter(Mandatory = $true)] + $SettingDefinition, + + [Parameter(Mandatory = $true)] + [System.String] + $SettingName, + + [Parameter(Mandatory = $true)] + [System.Array] + $SettingsWithSameName + ) + + $skip = 0 + $breakCounter = 0 + $threshold = 8 + $newSettingName = $SettingName + do { + $previousSettingName = $newSettingName + $newSettingName = Get-SettingDefinitionNameFromOffsetUri -OffsetUri $SettingDefinition.OffsetUri -SettingName $newSettingName -Skip $skip + + $combinationMatchesWithOffsetUri = @() + $SettingsWithSameName | ForEach-Object { + $newName = Get-SettingDefinitionNameFromOffsetUri -OffsetUri $_.OffsetUri -SettingName $previousSettingName -Skip $skip + if ($newName -eq $newSettingName) + { + # Exclude v2 versions from the comparison + if ($SettingDefinition.Id -like "*_v2" -and $_.Id -ne $SettingDefinition.Id.Replace('_v2', '') -or + $SettingDefinition.Id -notlike "*_v2" -and $_.Id -ne $SettingDefinition.Id + "_v2") + { + $combinationMatchesWithOffsetUri += $_ + } + } + } + $SettingsWithSameName = $combinationMatchesWithOffsetUri + $skip++ + $breakCounter++ + } while ($combinationMatchesWithOffsetUri.Count -gt 1 -and $breakCounter -lt $threshold) + + $success = $false + if ($breakCounter -lt $threshold) + { + if ($SettingDefinition.Id -like "*_v2" -and $newSettingName -notlike "*_v2") + { + $newSettingName += "_v2" + } + $settingName = $newSettingName + $success = $true + } + + @{ + Success = $success + SettingName = $settingName + } +} + +function Get-SettingDefinitionNameFromOffsetUri { param ( [Parameter(Mandatory = $true)] [System.String] diff --git a/ResourceGenerator/M365DSCResourceGenerator.psm1 b/ResourceGenerator/M365DSCResourceGenerator.psm1 index 6bac59401b..085b2decca 100644 --- a/ResourceGenerator/M365DSCResourceGenerator.psm1 +++ b/ResourceGenerator/M365DSCResourceGenerator.psm1 @@ -57,10 +57,14 @@ function New-M365DSCResource $DateFormat = "o", # SettingTemplates for DeviceManagementConfigurationPolicy - [Parameter()] + [Parameter(ParameterSetName = 'SettingsCatalog')] [System.Array] $SettingsCatalogSettingTemplates, + [Parameter(ParameterSetName = 'SettingsCatalog')] + [switch] + $SkipPlatformsAndTechnologies, + # Use this switch with caution. # Navigation Properties could cause the DRG to enter an infinite loop # Navigation Properties are the properties refered as Relationships in the Graph REST API documentation. @@ -213,6 +217,12 @@ function New-M365DSCResource $addIntuneAssignments = $true $ParametersToSkip += 'Assignments' } + + if ($SkipPlatformsAndTechnologies) + { + $ParametersToSkip += 'Platforms' + $ParametersToSkip += 'Technologies' + } } $parameterInformation = $parameterInformation | Where-Object -FilterScript {$_.Name -notin $ParametersToSkip} @@ -3918,7 +3928,8 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { } $instanceName = "MSFT_MicrosoftGraphIntuneSettingsCatalog" - if (($Level -gt 1 -and $type -like "GroupCollection*" -and $childSettings.Count -gt 1) -or ($Level -eq 1 -and $type -like "GroupCollection*" -and $SettingDefinition.AdditionalProperties.maximumCount -gt 1)) + if (($Level -gt 1 -and $type -like "GroupCollection*" -and $childSettings.Count -gt 1) -or + ($Level -eq 1 -and $type -like "GroupCollection*" -and $childSettings.Count -ge 1 -and $childSettings.AdditionalProperties.'@odata.type' -notcontains "#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition")) { $instanceName = $ParentInstanceName + $settingName } @@ -3945,7 +3956,7 @@ function New-SettingsCatalogSettingDefinitionSettingsFromTemplate { ChildSettings = $innerChildSettings } - if ($type -eq "GroupCollectionCollection" -and $childSettings.Count -eq 1) + if ($type -eq "GroupCollectionCollection" -and $childSettings.Count -eq 1 -and $SettingDefinition.AdditionalProperties.maximumCount -eq 1) { # Reset type and make child setting a collection $setting.Type = "GroupCollection" diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyLinux.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyLinux.Tests.ps1 new file mode 100644 index 0000000000..7a1c5db2da --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneAntivirusPolicyLinux.Tests.ps1 @@ -0,0 +1,683 @@ +[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 "IntuneAntivirusPolicyLinux" -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 = '12345-12345-12345-12345-12345' + } + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicy -MockWith { + return @{ + Id = '12345-12345-12345-12345-12345' + Description = 'My Test' + Name = 'My Test' + RoleScopeTagIds = @("FakeStringValue") + TemplateReference = @{ + TemplateId = '4cfd164c-5e8a-4ea9-b15d-9aa71e4ffff4_1' + } + } + } + + Mock -CommandName Remove-MgBetaDeviceManagementConfigurationPolicy -MockWith { + } + + Mock -CommandName Update-IntuneDeviceConfigurationPolicy -MockWith { + } + + Mock -CommandName Get-IntuneSettingCatalogPolicySetting -MockWith { + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicySetting -MockWith { + return @( + @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_cloudservice_enabled' + Name = 'enabled' + OffsetUri = 'enabled' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_cloudservice_enabled' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'ad8554ce-16d5-44a5-9686-d286844755b0' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + choiceSettingValue = @{ + children = @() + value = 'linux_mdatp_managed_cloudservice_enabled_true' + } + } + } + }, + @{ + Id = 1 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_disallowedthreatactions' + Name = 'disallowedThreatActions' + OffsetUri = 'disallowedThreatActions' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionDefinition' + maximumCount = 600 + minimumCount = 0 + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_antivirusengine_disallowedthreatactions' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'd1673a55-f037-4eca-b037-89392341d1b8' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionInstance' + simpleSettingCollectionValue = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = 'disallowed action 1' + } + ) + } + } + }, + @{ + Id = 2 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions' + Name = 'exclusions' + OffsetUri = 'exclusions' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + maximumCount = 600 + minimumCount = 0 + childIds = @( + 'linux_mdatp_managed_antivirusengine_exclusions_item_$type', + 'linux_mdatp_managed_antivirusengine_exclusions_item_extension' + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type' + Name = 'exclusions_item_$type' + OffsetUri = 'exclusions_item_$type' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type_1' + name = 'Path' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_exclusions' + parentSettingId = 'linux_mdatp_managed_antivirusengine_exclusions' + } + ) + } + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions_item_extension' + Name = 'exclusions_item_extension' + OffsetUri = 'exclusions/[{0}]/extension' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type_1' + parentSettingId = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type' + } + ) + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_antivirusengine_exclusions' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = 'e2d557ab-357e-4727-978e-0d655facbb23' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type' + choiceSettingValue = @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingInstance' + settingDefinitionId = 'linux_mdatp_managed_antivirusengine_exclusions_item_extension' + simpleSettingValue = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationStringSettingValue' + value = '.exe' + } + } + ) + value = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type_1' + } + } + ) + } + ) + } + } + }, + @{ + Id = 3 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings' + Name = 'threatTypeSettings' + OffsetUri = 'threatTypeSettings' + AdditionalProperties = @{ + maximumCount = 2147483647 + minimumCount = 0 + childIds = @( + 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key' + 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value' + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key' + Name = 'threatTypeSettings_item_key' + OffsetUri = 'threatTypeSettings/[{0}]/key' + AdditionalProperties = @{ + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key_0' + name = 'potentially_unwanted_application' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_threattypesettings' + parentSettingId = 'linux_mdatp_managed_antivirusengine_threattypesettings' + } + ) + } + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value' + Name = 'threatTypeSettings_item_value' + OffsetUri = 'threatTypeSettings/[{0}]/value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value_0' + name = 'audit' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_threattypesettings' + parentSettingId = 'linux_mdatp_managed_antivirusengine_threattypesettings' + } + ) + } + ) + } + } + ) + SettingInstance = @{ + SettingDefinitionId = 'linux_mdatp_managed_antivirusengine_threattypesettings' + SettingInstanceTemplateReference = @{ + SettingInstanceTemplateId = '2e407734-2d3a-4cc2-9a81-4d1c54718096' + } + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationGroupSettingCollectionInstance' + groupSettingCollectionValue = @( + @{ + children = @( + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key' + choiceSettingValue = @{ + children = @() + value = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key_0' + } + }, + @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingInstance' + settingDefinitionId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value' + choiceSettingValue = @{ + children = @() + value = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value_0' + } + } + ) + } + ) + } + } + } + ) + } + + Mock -CommandName Get-MgBetaDeviceManagementConfigurationPolicyTemplateSettingTemplate -MockWith { + return @( + @{ + Id = 0 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_cloudservice_enabled' + Name = 'enabled' + OffsetUri = 'enabled' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + } + } + ) + SettingInstance = @{ + # Not necessary + } + }, + @{ + Id = 1 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_disallowedthreatactions' + Name = 'disallowedThreatActions' + OffsetUri = 'disallowedThreatActions' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingCollectionDefinition' + maximumCount = 600 + minimumCount = 0 + } + } + ) + SettingInstance = @{ + # Not necessary + } + }, + @{ + Id = 2 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions' + Name = 'exclusions' + OffsetUri = 'exclusions' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSettingGroupCollectionDefinition' + maximumCount = 600 + minimumCount = 0 + childIds = @( + 'linux_mdatp_managed_antivirusengine_exclusions_item_$type', + 'linux_mdatp_managed_antivirusengine_exclusions_item_extension' + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type' + Name = 'exclusions_item_$type' + OffsetUri = 'exclusions_item_$type' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type_1' + name = 'Path' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_exclusions' + parentSettingId = 'linux_mdatp_managed_antivirusengine_exclusions' + } + ) + } + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_exclusions_item_extension' + Name = 'exclusions_item_extension' + OffsetUri = 'exclusions/[{0}]/extension' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationSimpleSettingDefinition' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type_1' + parentSettingId = 'linux_mdatp_managed_antivirusengine_exclusions_item_$type' + } + ) + } + } + ) + SettingInstance = @{ + # Not necessary + } + }, + @{ + Id = 3 + SettingDefinitions = @( + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings' + Name = 'threatTypeSettings' + OffsetUri = 'threatTypeSettings' + AdditionalProperties = @{ + maximumCount = 2147483647 + minimumCount = 0 + childIds = @( + 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key' + 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value' + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key' + Name = 'threatTypeSettings_item_key' + OffsetUri = 'threatTypeSettings/[{0}]/key' + AdditionalProperties = @{ + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_key_0' + name = 'potentially_unwanted_application' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_threattypesettings' + parentSettingId = 'linux_mdatp_managed_antivirusengine_threattypesettings' + } + ) + } + ) + } + }, + @{ + Id = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value' + Name = 'threatTypeSettings_item_value' + OffsetUri = 'threatTypeSettings/[{0}]/value' + AdditionalProperties = @{ + '@odata.type' = '#microsoft.graph.deviceManagementConfigurationChoiceSettingDefinition' + options = @( + @{ + itemId = 'linux_mdatp_managed_antivirusengine_threattypesettings_item_value_0' + name = 'audit' + dependentOn = @( + @{ + dependentOn = 'linux_mdatp_managed_antivirusengine_threattypesettings' + parentSettingId = 'linux_mdatp_managed_antivirusengine_threattypesettings' + } + ) + } + ) + } + } + ) + SettingInstance = @{ + # Not necessary + } + } + ) + } + + Mock -CommandName Update-DeviceConfigurationPolicyAssignment -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + + Mock -CommandName Get-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 IntuneAntivirusPolicyLinux 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' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + disallowedThreatActions = @("disallowed action 1") + enabled = "true"; + exclusions = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions -Property @{ + Exclusions_item_extension = '.exe' + Exclusions_item_type = '1' + } -ClientOnly) + ); + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + threatTypeSettings = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings -Property @{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } -ClientOnly) + ); + 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 IntuneAntivirusPolicyLinux 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' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + disallowedThreatActions = @("disallowed action 1") + enabled = "true"; + exclusions = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions -Property @{ + Exclusions_item_extension = '.exe' + Exclusions_item_type = '1' + } -ClientOnly) + ); + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + threatTypeSettings = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings -Property @{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } -ClientOnly) + ); + 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 IntuneAntivirusPolicyLinux 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' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + disallowedThreatActions = @("disallowed action 1") + enabled = "true"; + exclusions = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions -Property @{ + Exclusions_item_extension = '.exe' + Exclusions_item_type = '1' + } -ClientOnly) + ); + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + threatTypeSettings = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings -Property @{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } -ClientOnly) + ); + Ensure = "Present" + Credential = $Credential; + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The IntuneAntivirusPolicyLinux 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' + deviceAndAppManagementAssignmentFilterType = 'none' + } -ClientOnly) + ) + Description = "My Test" + disallowedThreatActions = @("disallowed action 1") + enabled = "true"; + exclusions = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogExclusions -Property @{ + Exclusions_item_extension = '.pdf' # Drift + Exclusions_item_type = '1' + } -ClientOnly) + ); + Id = "12345-12345-12345-12345-12345" + DisplayName = "My Test" + RoleScopeTagIds = @("FakeStringValue") + threatTypeSettings = [CimInstance[]]@( + (New-CimInstance -ClassName MSFT_MicrosoftGraphIntuneSettingsCatalogThreatTypeSettings -Property @{ + ThreatTypeSettings_item_key = '0' + ThreatTypeSettings_item_value = '0' + } -ClientOnly) + ); + Ensure = "Present" + Credential = $Credential; + } + } + + 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 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 index d95d8ba48d..b15984720e 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.IntuneDeviceControlPolicyWindows10.Tests.ps1 @@ -669,7 +669,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - It 'Should return true from the Test method' { Test-TargetResource @testParams | Should -Be $true }