From 6fb560250f116f15473594d30ef13a9eeac07c2a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:18:54 -0400 Subject: [PATCH 1/4] SCDeviceConfigurationRule - Initial Release --- CHANGELOG.md | 2 + .../MSFT_SCDeviceConfigurationRule.psm1 | 1060 +++++++++++++++++ .../MSFT_SCDeviceConfigurationRule.schema.mof | 62 + .../MSFT_SCDeviceConfigurationRule/readme.md | 6 + .../settings.json | 28 + .../SCDeviceConfigurationRule/1-Create.ps1 | 59 + .../SCDeviceConfigurationRule/2-Update.ps1 | 59 + .../SCDeviceConfigurationRule/3-Remove.ps1 | 34 + ...365DSC.SCDeviceConfigurationRule.Tests.ps1 | 399 +++++++ 9 files changed, 1709 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 create mode 100644 Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b538b36b..2c6727ac8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ FIXES [#5034](https://github.com/microsoft/Microsoft365DSC/issues/5034) * SCDeviceConditionalAccessRule * Initial release. +* SCDeviceConfigurationRule + * Initial release. * SCInsiderRiskEntityList * Initial release. * SCRoleGroup diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 new file mode 100644 index 000000000..40c55c630 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 @@ -0,0 +1,1060 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'SecurityComplianceCenter' ` + -InboundParameters $PSBoundParameters | Out-Null + + New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters | Out-Null + + #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' + try + { + $policyObj = Get-DeviceConfigurationPolicy | Where-Object -FilterScript {$_.Name -eq $Policy} + if ($null -ne $policyObj) + { + Write-Verbose -Message "Found policy object {$Policy}" + if ($null -ne $Script:exportedInstances -and $Script:ExportMode -and $null) + { + $instance = $Script:exportedInstances | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + else + { + $instance = Get-DeviceConfigurationRule | Where-Object -FilterScript {$_.Policy -eq $policyObj.ExchangeObjectId} + } + } + if ($null -eq $instance) + { + return $nullResult + } + + $groupNames = @() + foreach ($group in $instance.TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -GroupId $group.Guid -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group.Guid -ErrorAction SilentlyContinue + $groupValue = $entry.UserPrincipalName + } + else + { + $groupValue = $entry.DisplayName + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $groupNames += $groupValue + } + } + + $results = @{ + Name = $instance.Name + Policy = $policyObj.Name + TargetGroups = $groupNames + AccountName = $instance.AccountName + AccountUserName = $instance.AccountUserName + AllowAppStore = $instance.AllowAppStore + AllowAssistantWhileLocked = $instance.AllowAssistantWhileLocked + AllowConvenienceLogon = $instance.AllowConvenienceLogon + AllowDiagnosticSubmission = $instance.AllowDiagnosticSubmission + AllowiCloudBackup = $instance.AllowiCloudBackup + AllowiCloudDocSync = $instance.AllowiCloudDocSync + AllowiCloudPhotoSync = $instance.AllowiCloudPhotoSync + AllowPassbookWhileLocked = $instance.AllowPassbookWhileLocked + AllowScreenshot = $instance.AllowScreenshot + AllowSimplePassword = $instance.AllowSimplePassword + AllowVideoConferencing = $instance.AllowVideoConferencing + AllowVoiceAssistant = $instance.AllowVoiceAssistant + AllowVoiceDialing = $instance.AllowVoiceDialing + AntiVirusSignatureStatus = $instance.AntiVirusSignatureStatus + AntiVirusStatus = $instance.AntiVirusStatus + AppsRating = $instance.AppsRating + AutoUpdateStatus = $instance.AutoUpdateStatus + BluetoothEnabled = $instance.BluetoothEnabled + CameraEnabled = $instance.CameraEnabled + EmailAddress = $instance.EmailAddress + EnableRemovableStorage = $instance.EnableRemovableStorage + ExchangeActiveSyncHost = $instance.ExchangeActiveSyncHost + FirewallStatus = $instance.FirewallStatus + ForceAppStorePassword = $instance.ForceAppStorePassword + ForceEncryptedBackup = $instance.ForceEncryptedBackup + MaxPasswordAttemptsBeforeWipe = $instance.MaxPasswordAttemptsBeforeWipe + MaxPasswordGracePeriod = $instance.MaxPasswordGracePeriod + MoviesRating = $instance.MoviesRating + PasswordComplexity = $instance.PasswordComplexity + PasswordExpirationDays = $instance.PasswordExpirationDays + PasswordHistoryCount = $instance.PasswordHistoryCount + PasswordMinComplexChars = $instance.PasswordMinComplexChars + PasswordMinimumLength = $instance.PasswordMinimumLength + PasswordQuality = $instance.PasswordQuality + PasswordRequired = $instance.PasswordRequired + PasswordTimeout = $instance.PasswordTimeout + PhoneMemoryEncrypted = $instance.PhoneMemoryEncrypted + RegionRatings = $instance.RegionRatings + RequireEmailProfile = $instance.RequireEmailProfile + SmartScreenEnabled = $instance.SmartScreenEnabled + SystemSecurityTLS = $instance.SystemSecurityTLS + TVShowsRating = $instance.TVShowsRating + UserAccountControlStatus = $instance.UserAccountControlStatus + WLANEnabled = $instance.WLANEnabled + WorkFoldersSyncUrl = $instance.WorkFoldersSyncUrl + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [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 + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $setParameters.Remove('Name') | Out-Null + + if ($Ensure -eq 'Present' -and $null -ne $TargetGroups) + { + $targetGroupsValue = @() + foreach ($group in $TargetGroups) + { + $groupValue = '' + $entry = Get-MgGroup -Filter "DisplayName eq '$group'" -ErrorAction SilentlyContinue + if ($null -eq $entry) + { + $entry = Get-MgUser -UserId $group -ErrorAction SilentlyContinue + $groupValue = $entry.Id + } + else + { + $groupValue = $entry.Id + } + + if ($null -eq $entry) + { + Write-Error -Message "Could not find group or user identified with id {$group}" + } + else + { + $targetGroupsValue += $groupValue + } + } + $setParameters.TargetGroups = $targetGroupsValue + } + + # CREATE + if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') + { + Write-Verbose -Message "Creating new device configuration rule {$Name}" + New-DeviceConfigurationRule @setParameters + } + # UPDATE + elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present') + { + $setParameters.Remove('Policy') | Out-Null + $setParameters.Add('Identity', $currentInstance.Name) + Write-Verbose -Message "Updating device configuration rule {$Name}" + Set-DeviceConfigurationRule @setParameters + } + # REMOVE + elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') + { + Write-Verbose -Message "Removing device configuration rule {$Name}" + Remove-DeviceConfigurationRuleDeviceConditionalAccessRule -Identity $currentInstance.Name -Confirm:$false + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Name, + + [Parameter(Mandatory = $true)] + [System.String] + $Policy, + + [Parameter(Mandatory = $true)] + [System.String[]] + $TargetGroups, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Boolean] + $AllowAppStore, + + [Parameter()] + [System.Boolean] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowConvenienceLogon, + + [Parameter()] + [System.Boolean] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Boolean] + $AllowiCloudBackup, + + [Parameter()] + [System.Boolean] + $AllowiCloudDocSync, + + [Parameter()] + [System.Boolean] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Boolean] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Boolean] + $AllowScreenshot, + + [Parameter()] + [System.Boolean] + $AllowSimplePassword, + + [Parameter()] + [System.Boolean] + $AllowVideoConferencing, + + [Parameter()] + [System.Boolean] + $AllowVoiceAssistant, + + [Parameter()] + [System.Boolean] + $AllowVoiceDialing, + + [Parameter()] + [System.UInt32] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.UInt32] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $AppsRating, + + [Parameter()] + [System.String] + $AutoUpdateStatus, + + [Parameter()] + [System.Boolean] + $BluetoothEnabled, + + [Parameter()] + [System.Boolean] + $CameraEnabled, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Boolean] + $EnableRemovableStorage, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Boolean] + $FirewallStatus, + + [Parameter()] + [System.Boolean] + $ForceAppStorePassword, + + [Parameter()] + [System.Boolean] + $ForceEncryptedBackup, + + [Parameter()] + [System.UInt32] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.UInt32] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.String] + $MoviesRating, + + [Parameter()] + [System.UInt32] + $PasswordComplexity, + + [Parameter()] + [System.UInt32] + $PasswordExpirationDays, + + [Parameter()] + [System.UInt32] + $PasswordHistoryCount, + + [Parameter()] + [System.UInt32] + $PasswordMinComplexChars, + + [Parameter()] + [System.UInt32] + $PasswordMinimumLength, + + [Parameter()] + [System.UInt32] + $PasswordQuality, + + [Parameter()] + [System.Boolean] + $PasswordRequired, + + [Parameter()] + [System.String] + $PasswordTimeout, + + [Parameter()] + [System.Boolean] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $RegionRatings, + + [Parameter()] + [System.Boolean] + $RequireEmailProfile, + + [Parameter()] + [System.Boolean] + $SmartScreenEnabled, + + [Parameter()] + [System.Boolean] + $SystemSecurityTLS, + + [Parameter()] + [System.String] + $TVShowsRating, + + [Parameter()] + [System.String] + $UserAccountControlStatus, + + [Parameter()] + [System.Boolean] + $WLANEnabled, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [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 + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + $ValuesToCheck.Remove('Name') | Out-Null + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $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.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 'SecurityComplianceCenter' ` + -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 + { + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-DeviceConfigurationRule -ErrorAction Stop + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.Name + Write-Host " |---[$i/$($Script:exportedInstances.Count)] $displayedKey" -NoNewline + $params = @{ + Name = $config.Name + Policy = $config.Name.Split('{')[0] + TargetGroups = $config.TargetGroups + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $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_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof new file mode 100644 index 000000000..183b485c1 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof @@ -0,0 +1,62 @@ +[ClassVersion("1.0.0.0"), FriendlyName("SCDeviceConfigurationRule")] +class MSFT_SCDeviceConfigurationRule : OMI_BaseResource +{ + [Key, Description("Name for the rule.")] String Name; + [Write, Description("Name of the associated policy.")] String Policy; + [Write, Description("The display names of the graoups targeted by the policy.")] String TargetGroups[]; + [Write, Description("The AccountName parameter specifies the account name.")] String AccountName; + [Write, Description("The AccountUserName parameter specifies the account user name.")] String AccountUserName; + [Write, Description("The AllowAppStore parameter specifies whether to allow access to the app store on devices.")] Boolean AllowAppStore; + [Write, Description("The AllowAssistantWhileLocked parameter specifies whether to allow the use of the voice assistant while devices are locked.")] Boolean AllowAssistantWhileLocked; + [Write, Description("The AllowConvenienceLogon parameter specifies whether to allow convenience logons on devices.")] Boolean AllowConvenienceLogon; + [Write, Description("The AllowDiagnosticSubmission parameter specifies whether to allow diagnostic submissions from devices.")] Boolean AllowDiagnosticSubmission; + [Write, Description("The AllowiCloudBackup parameter specifies whether to allow Apple iCloud Backup from devices.")] Boolean AllowiCloudBackup; + [Write, Description("The AllowiCloudDocSync parameter specifies whether to allow Apple iCloud Documents & Data sync on devices.")] Boolean AllowiCloudDocSync; + [Write, Description("The AllowiCloudPhotoSync parameter specifies whether to allow Apple iCloud Photos sync on devices.")] Boolean AllowiCloudPhotoSync; + [Write, Description("The AllowPassbookWhileLocked parameter specifies whether to allow the use of Apple Passbook while devices are locked.")] Boolean AllowPassbookWhileLocked; + [Write, Description("The AllowScreenshot parameter specifies whether to allow screenshots on devices.")] Boolean AllowScreenshot; + [Write, Description("The AllowSimplePassword parameter specifies whether to allow simple or non-complex passwords on devices.")] Boolean AllowSimplePassword; + [Write, Description("The AllowVideoConferencing parameter specifies whether to allow video conferencing on devices. ")] Boolean AllowVideoConferencing; + [Write, Description("The AllowVoiceAssistant parameter specifies whether to allow using the voice assistant on devices.")] Boolean AllowVoiceAssistant; + [Write, Description("The AllowVoiceDialing parameter specifies whether to allow voice-activated telephone dialing.")] Boolean AllowVoiceDialing; + [Write, Description("The AntiVirusSignatureStatus parameter specifies the antivirus signature status.")] UInt32 AntiVirusSignatureStatus; + [Write, Description("The AntiVirusStatus parameter specifies the antivirus status.")] UInt32 AntiVirusStatus; + [Write, Description("The AppsRating parameter species the maximum or most restrictive rating of apps that are allowed on devices.")] String AppsRating; + [Write, Description("The AutoUpdateStatus parameter specifies the update settings for devices.")] String AutoUpdateStatus; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean BluetoothEnabled; + [Write, Description("The BluetoothEnabled parameter specifies whether to enable or disable Bluetooth on devices.")] Boolean CameraEnabled; + [Write, Description("The EmailAddress parameter specifies the email address.")] String EmailAddress; + [Write, Description("The EnableRemovableStorage parameter specifies whether removable storage can be used by devices.")] Boolean EnableRemovableStorage; + [Write, Description("The ExchangeActiveSyncHost parameter specifies the Exchange ActiveSync host.")] String ExchangeActiveSyncHost; + [Write, Description("The FirewallStatus parameter specifies the acceptable firewall status values on devices.")] Boolean FirewallStatus; + [Write, Description("The ForceAppStorePassword parameter specifies whether to require a password to use the app store on devices.")] Boolean ForceAppStorePassword; + [Write, Description("The ForceEncryptedBackup parameter specifies whether to force encrypted backups for devices.")] Boolean ForceEncryptedBackup; + [Write, Description("The MaxPasswordAttemptsBeforeWipe parameter specifies the number of incorrect password attempts that cause devices to be automatically wiped.")] UInt32 MaxPasswordAttemptsBeforeWipe; + [Write, Description("The MaxPasswordGracePeriod parameter specifies the length of time users are allowed to reset expired passwords on devices.")] UInt32 MaxPasswordGracePeriod; + [Write, Description("The MoviesRating parameter species the maximum or most restrictive rating of movies that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String MoviesRating; + [Write, Description("The PasswordComplexity parameter specifies the password complexity.")] UInt32 PasswordComplexity; + [Write, Description("The PasswordExpirationDays parameter specifies the number of days that the same password can be used on devices before users are required to change their passwords.")] UInt32 PasswordExpirationDays; + [Write, Description("The PasswordHistoryCount parameter specifies the minimum number of unique new passwords that are required on devices before an old password can be reused.")] UInt32 PasswordHistoryCount; + [Write, Description("The PasswordMinComplexChars parameter specifies the minimum number of complex characters that are required for device passwords. A complex character isn't a letter.")] UInt32 PasswordMinComplexChars; + [Write, Description("The PasswordMinimumLength parameter specifies the minimum number of characters that are required for device passwords.")] UInt32 PasswordMinimumLength; + [Write, Description("The PasswordQuality parameter specifies the minimum password quality rating that's required for device passwords. Password quality is a numeric scale that indicates the security and complexity of the password. A higher quality value indicates a more secure password.")] UInt32 PasswordQuality; + [Write, Description("The PasswordRequired parameter specifies whether a password is required to access devices.")] Boolean PasswordRequired; + [Write, Description("The PasswordTimeout parameter specifies the length of time that devices can be inactive before a password is required to reactivate them.")] String PasswordTimeout; + [Write, Description("The PhoneMemoryEncrypted parameter specifies whether to encrypt the memory on devices.")] Boolean PhoneMemoryEncrypted; + [Write, Description("The RegionRatings parameter specifies the rating system (country/region) to use for movie and television ratings with the MoviesRating and TVShowsRating parameters.")] String RegionRatings; + [Write, Description("The RequireEmailProfile parameter specifies whether an email profile is required on devices.")] Boolean RequireEmailProfile; + [Write, Description("The SmartScreenEnabled parameter specifies whether to requireWindows SmartScreen on devices.")] Boolean SmartScreenEnabled; + [Write, Description("The SystemSecurityTLS parameter specifies whether TLS encryption is used on devices.")] Boolean SystemSecurityTLS; + [Write, Description("The TVShowsRating parameter species the maximum or most restrictive rating of television shows that are allowed on devices. You specify the country/region rating system to use with the RegionRatings parameter.")] String TVShowsRating; + [Write, Description("The UserAccountControlStatus parameter specifies how User Account Control messages are presented on devices.")] String UserAccountControlStatus; + [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; + [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Credentials of the workload's 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("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_SCDeviceConfigurationRule/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md new file mode 100644 index 000000000..881ff8713 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/readme.md @@ -0,0 +1,6 @@ + +# SCDeviceConfigurationRule + +## Description + +This resource configures a Device Configuration Rule in Purview. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json new file mode 100644 index 000000000..dc6636d9d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/settings.json @@ -0,0 +1,28 @@ +{ + "resourceName": "SCDeviceConfigurationRule", + "description": "This resource configures a Device Configuration Rule in Purview.", + "roles": { + "read": [], + "update": [] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Group.Read.All" + } + ], + "update": [ + { + "name": "Group.Read.All" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 new file mode 100644 index 000000000..d9b2278f0 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/1-Create.ps1 @@ -0,0 +1,59 @@ +<# +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 + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 new file mode 100644 index 000000000..abcbc2eda --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/2-Update.ps1 @@ -0,0 +1,59 @@ +<# +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 + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $False; # Drift + AllowVoiceDialing = $True; + ApplicationId = $ApplicationId; + BluetoothEnabled = $True; + CameraEnabled = $True; + CertificateThumbprint = $CertificateThumbprint; + EnableRemovableStorage = $True; + Ensure = "Present"; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyDeviceConfigurationPolicy{2b18}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyDeviceConfigurationPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("All Company"); + TenantId = $TenantId; + WLANEnabled = $True; + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/3-Remove.ps1 new file mode 100644 index 000000000..249a846db --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/SCDeviceConfigurationRule/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 + { + SCDeviceConfigurationRule "MyDeviceConfigurationRule" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Absent"; + Name = "MyDeviceConfigurationPolicy{2b18}"; + Policy = "MyDeviceConfigurationPolicy"; + TenantId = $TenantId; + } + } +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 new file mode 100644 index 000000000..6d40bd578 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 @@ -0,0 +1,399 @@ +[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) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -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 New-M365DSCConnection -MockWith { + return "Credentials" + } + + Mock -CommandName New-DeviceConfigurationRule -MockWith { + } + + Mock -CommandName Set-DeviceConfigurationRule -MockWith { + } + + Mock -CommandName Remove-DeviceConfigurationRule -MockWith { + } + + Mock -Command Get-MgGroup -MockWith { + return @{ + Id = "33333-33333-33333-33333-33333" + DisplayName = 'Communications' + } + } + + Mock -CommandName Get-DeviceConditionalAccessPolicy -MockWith { + return @{ + Name = 'MyPolicy' + Id = '12345-12345-12345-12345-12345' + } + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -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 a new instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName New-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name "The instance exists but it SHOULD NOT" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Absent' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + 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 remove the instance from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $True; + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + Name = "MyPolicy{394b}"; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + Policy = "MyPolicy"; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + TargetGroups = @("Communications"); + WLANEnabled = $True; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + + 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 Set-DeviceConfigurationRule -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Get-DeviceConfigurationRule -MockWith { + return @{ + Id = '11111-11111-11111-11111-11111' + Name = 'MyPolicy{394b}' + TargetGroups = @('22222-22222-22222-22222-22222') + AllowAppStore = $True; + AllowAssistantWhileLocked = $True; + AllowConvenienceLogon = $True; + AllowDiagnosticSubmission = $True; + AllowiCloudBackup = $True; + AllowiCloudDocSync = $True; + AllowiCloudPhotoSync = $True; + AllowPassbookWhileLocked = $True; + AllowScreenshot = $False; #Drift + AllowSimplePassword = $True; + AllowVideoConferencing = $True; + AllowVoiceAssistant = $True; + AllowVoiceDialing = $True; + BluetoothEnabled = $True; + CameraEnabled = $True; + EnableRemovableStorage = $True; + ForceAppStorePassword = $False; + ForceEncryptedBackup = $False; + PasswordRequired = $False; + PhoneMemoryEncrypted = $False; + RequireEmailProfile = $False; + SmartScreenEnabled = $False; + SystemSecurityTLS = $False; + WLANEnabled = $True; + } + } + } + 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 f4a86fe9c0093b224c65b9e40d200325109c210a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:30:51 -0400 Subject: [PATCH 2/4] Update MSFT_SCDeviceConfigurationRule.schema.mof --- .../MSFT_SCDeviceConfigurationRule.schema.mof | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof index 183b485c1..f21d833b0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.schema.mof @@ -52,7 +52,7 @@ class MSFT_SCDeviceConfigurationRule : OMI_BaseResource [Write, Description("The WLANEnabled parameter specifies whether Wi-Fi is enabled devices.")] Boolean WLANEnabled; [Write, Description("The WorkFoldersSyncUrl parameter specifies the URL that's used to synchronize company data on devices.")] String WorkFoldersSyncUrl; - [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Present"}, Values{"Present"}] string Ensure; + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent", "Present"}, Values{"Absent", "Present"}] string Ensure; [Write, Description("Credentials of the workload's 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; From 39ff34f887f784c59a7a237576a74d255ea20f4e Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 10:53:12 -0400 Subject: [PATCH 3/4] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 449 +++++++++++++++++++++++++++++ 1 file changed, 449 insertions(+) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index 60ca7a79e..7d67c6689 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -64770,6 +64770,455 @@ function Get-DeviceConfigurationPolicy $Identity ) } +function Get-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $CompareToWorkload, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $DomainController + ) +} +function New-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $Policy, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} +function Remove-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity + ) +} +function Set-DeviceConfigurationRule +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $CameraEnabled, + + [Parameter()] + [System.Object] + $EnableRemovableStorage, + + [Parameter()] + [System.Object] + $AntiVirusSignatureStatus, + + [Parameter()] + [System.Object] + $FirewallStatus, + + [Parameter()] + [System.Object] + $AllowAppStore, + + [Parameter()] + [System.Object] + $AllowAssistantWhileLocked, + + [Parameter()] + [System.Object] + $AllowiCloudBackup, + + [Parameter()] + [System.Object] + $AppsRating, + + [Parameter()] + [System.Object] + $PasswordHistoryCount, + + [Parameter()] + [System.Object] + $PasswordQuality, + + [Parameter()] + [System.Object] + $PasswordMinComplexChars, + + [Parameter()] + [System.Object] + $PhoneMemoryEncrypted, + + [Parameter()] + [System.String] + $EmailAddress, + + [Parameter()] + [System.Object] + $BluetoothEnabled, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $AllowConvenienceLogon, + + [Parameter()] + [System.Object] + $MaxPasswordGracePeriod, + + [Parameter()] + [System.Object] + $AllowiCloudDocSync, + + [Parameter()] + [System.Object] + $ForceAppStorePassword, + + [Parameter()] + [System.Object] + $TVShowsRating, + + [Parameter()] + [System.String] + $ExchangeActiveSyncHost, + + [Parameter()] + [System.Object] + $RequireEmailProfile, + + [Parameter()] + [System.Object] + $AllowDiagnosticSubmission, + + [Parameter()] + [System.Object] + $AutoUpdateStatus, + + [Parameter()] + [System.String] + $AccountUserName, + + [Parameter()] + [System.Object] + $WLANEnabled, + + [Parameter()] + [System.Object] + $AllowVoiceDialing, + + [Parameter()] + [System.String] + $AccountName, + + [Parameter()] + [System.Object] + $PasswordExpirationDays, + + [Parameter()] + [System.Object] + $PasswordTimeout, + + [Parameter()] + [System.Object] + $AllowiCloudPhotoSync, + + [Parameter()] + [System.Object] + $AllowSimplePassword, + + [Parameter()] + [System.Object] + $AllowPassbookWhileLocked, + + [Parameter()] + [System.Object] + $PasswordMinimumLength, + + [Parameter()] + [System.Object] + $AllowVideoConferencing, + + [Parameter()] + [System.Object] + $PasswordRequired, + + [Parameter()] + [System.Object] + $MaxPasswordAttemptsBeforeWipe, + + [Parameter()] + [System.Object] + $MoviesRating, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $DomainController, + + [Parameter()] + [System.Object] + $AntiVirusStatus, + + [Parameter()] + [System.String] + $WorkFoldersSyncUrl, + + [Parameter()] + [System.Object] + $UserAccountControlStatus, + + [Parameter()] + [System.Object] + $ForceEncryptedBackup, + + [Parameter()] + [System.Object] + $AllowScreenshot, + + [Parameter()] + [System.Object] + $PasswordComplexity, + + [Parameter()] + [System.Object] + $TargetGroups, + + [Parameter()] + [System.Object] + $AllowVoiceAssistant, + + [Parameter()] + [System.Object] + $SystemSecurityTLS, + + [Parameter()] + [System.Object] + $RegionRatings, + + [Parameter()] + [System.Object] + $SmartScreenEnabled + ) +} + function Get-DlpCompliancePolicy { [CmdletBinding()] From 27a3a7b8b52f5beb8e461384d853a6e3d1e2c5ae Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 25 Sep 2024 11:08:47 -0400 Subject: [PATCH 4/4] updated Tests --- .../MSFT_SCDeviceConfigurationRule.psm1 | 2 +- .../Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 index 40c55c630..97f1c316a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDeviceConfigurationRule/MSFT_SCDeviceConfigurationRule.psm1 @@ -671,7 +671,7 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Removing device configuration rule {$Name}" - Remove-DeviceConfigurationRuleDeviceConditionalAccessRule -Identity $currentInstance.Name -Confirm:$false + Remove-DeviceConfigurationRule -Identity $currentInstance.Name -Confirm:$false } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 index 6d40bd578..de92d8b2e 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.SCDeviceConfigurationRule.Tests.ps1 @@ -51,7 +51,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } } - Mock -CommandName Get-DeviceConditionalAccessPolicy -MockWith { + Mock -CommandName Get-DeviceCOnfigurationPolicy -MockWith { return @{ Name = 'MyPolicy' Id = '12345-12345-12345-12345-12345'