diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b89a9c8f2..8a7284de00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Change log for Microsoft365DSC +# 1.25.108.1 + +* AADAuthenticationRequirement + * Changed Export logic to extract instances from all users. +* AADOrganizationCertificateBasedAuthConfiguration + * Fixed the primary key of the resource. + FIXES [#5523](https://github.com/microsoft/Microsoft365DSC/issues/5523) +* AADRoleEligibilityScheduleRequest + * Fixed error when extracting an entry with a deleted principal. +* DefenderDeviceAuthenticatedScanDefinition + * Fixed the Data Type export. +* MISC + * Added check to `New-M365DSCReportFromConfiguration` to make sure Windows + Remoting is enabled, which is required to convert the DSC config. + * Defender + * Added support for the UseBasicParsing parameter for REST calls. + # 1.24.1218.1 * AADApplication diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 index bb76b820b1..e8e8fae959 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationRequirement/MSFT_AADAuthenticationRequirement.psm1 @@ -310,7 +310,7 @@ function Export-TargetResource try { - [array]$getValue = Get-MgUser -ErrorAction Stop | Where-Object -FilterScript { $null -ne $_.Id } + [array]$getValue = Get-MgUser -ErrorAction Stop -All | Where-Object -FilterScript { $null -ne $_.Id } $i = 1 $dscContent = '' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADOrganizationCertificateBasedAuthConfiguration/MSFT_AADOrganizationCertificateBasedAuthConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADOrganizationCertificateBasedAuthConfiguration/MSFT_AADOrganizationCertificateBasedAuthConfiguration.psm1 index 109cc8b9a6..8a5b4423f2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADOrganizationCertificateBasedAuthConfiguration/MSFT_AADOrganizationCertificateBasedAuthConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADOrganizationCertificateBasedAuthConfiguration/MSFT_AADOrganizationCertificateBasedAuthConfiguration.psm1 @@ -9,7 +9,7 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $CertificateAuthorities, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $OrganizationId, #endregion @@ -141,7 +141,7 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $CertificateAuthorities, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $OrganizationId, #endregion @@ -225,7 +225,13 @@ function Set-TargetResource certificateAuthorities = $createCertAuthorities } - $policy = Invoke-MgGraphRequest -Uri ((Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + "beta/organization/$OrganizationId/certificateBasedAuthConfiguration/") -Method POST -Body $params + $uri = ((Get-MSCloudLoginConnectionProfile -Workload MicrosoftGraph).ResourceUrl + ` + "beta/organization/$OrganizationId/certificateBasedAuthConfiguration/") + + Write-Verbose -Message "Creating with Parameters:`r`n$(ConvertTo-Json $params -Depth 10)" + Invoke-MgGraphRequest -Uri $uri ` + -Method 'POST' ` + -Body $params } } @@ -240,7 +246,7 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $CertificateAuthorities, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $OrganizationId, #endregion @@ -417,6 +423,10 @@ function Export-TargetResource } foreach ($config in $getValue) { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } $displayedKey = "CertificateBasedAuthConfigurations for $($getValue.DisplayName)" Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline $params = @{ diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 index 3cebcf39a2..5091971e4f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 @@ -756,8 +756,15 @@ function Export-TargetResource if ($null -eq $groupInfo) { $principalType = 'ServicePrincipal' - $spnInfo = Get-MgServicePrincipal -ServicePrincipalId $request.PrincipalId - $PrincipalValue = $spnInfo.DisplayName + $spnInfo = Get-MgServicePrincipal -ServicePrincipalId $request.PrincipalId -ErrorAction SilentlyContinue + if ($null -ne $spnInfo) + { + $PrincipalValue = $spnInfo.DisplayName + } + else + { + $PrincipalValue = $null + } } else { @@ -769,61 +776,64 @@ function Export-TargetResource $PrincipalValue = $userInfo.UserPrincipalName } - $RoleDefinitionId = Get-MgBetaRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $request.RoleDefinitionId - $params = @{ - Id = $request.Id - Principal = $PrincipalValue - PrincipalType = $principalType - DirectoryScopeId = $request.DirectoryScopeId - RoleDefinition = $RoleDefinitionId.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - ManagedIdentity = $ManagedIdentity.IsPresent - AccessTokens = $AccessTokens - } + if ($null -ne $PrincipalValue) + { + $RoleDefinitionId = Get-MgBetaRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $request.RoleDefinitionId + $params = @{ + Id = $request.Id + Principal = $PrincipalValue + PrincipalType = $principalType + DirectoryScopeId = $request.DirectoryScopeId + RoleDefinition = $RoleDefinitionId.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } - $Results = Get-TargetResource @Params + $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - try - { - if ($null -ne $results.ScheduleInfo) + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + try { - $Results.ScheduleInfo = Get-M365DSCAzureADEligibilityRequestScheduleInfoAsString -ScheduleInfo $Results.ScheduleInfo + if ($null -ne $results.ScheduleInfo) + { + $Results.ScheduleInfo = Get-M365DSCAzureADEligibilityRequestScheduleInfoAsString -ScheduleInfo $Results.ScheduleInfo + } + } + catch + { + Write-Verbose -Message "Error converting Schedule: $_" + } + if ($Results.TicketInfo) + { + $Results.TicketInfo = Get-M365DSCAzureADEligibilityRequestTicketInfoAsString -TicketInfo $Results.TicketInfo + } + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($null -ne $Results.ScheduleInfo) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'ScheduleInfo' + } + if ($null -ne $Results.TicketInfo) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` + -ParameterName 'TicketInfo' } - } - catch - { - Write-Verbose -Message "Error converting Schedule: $_" - } - if ($Results.TicketInfo) - { - $Results.TicketInfo = Get-M365DSCAzureADEligibilityRequestTicketInfoAsString -TicketInfo $Results.TicketInfo - } - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - if ($null -ne $Results.ScheduleInfo) - { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` - -ParameterName 'ScheduleInfo' - } - if ($null -ne $Results.TicketInfo) - { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock ` - -ParameterName 'TicketInfo' - } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + } $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 index 8da0f80edd..b79636d69d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthority/MSFT_AADVerifiedIdAuthority.psm1 @@ -575,11 +575,11 @@ function Invoke-M365DSCVerifiedIdWebRequest if ($Method -eq 'PATCH' -or $Method -eq 'POST') { $BodyJson = $body | ConvertTo-Json - $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $BodyJson + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $BodyJson -UseBasicParsing } else { - $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -UseBasicParsing } if ($Method -eq 'DELETE') diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthorityContract/MSFT_AADVerifiedIdAuthorityContract.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthorityContract/MSFT_AADVerifiedIdAuthorityContract.psm1 index 0ff063c803..88225c80a0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthorityContract/MSFT_AADVerifiedIdAuthorityContract.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADVerifiedIdAuthorityContract/MSFT_AADVerifiedIdAuthorityContract.psm1 @@ -922,11 +922,11 @@ function Invoke-M365DSCVerifiedIdWebRequest if ($Method -eq 'PATCH' -or $Method -eq 'POST') { $BodyJson = $body | ConvertTo-Json -Depth 10 - $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $BodyJson + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -Body $BodyJson -UseBasicParsing } else { - $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers + $response = Invoke-WebRequest -Method $Method -Uri $Uri -Headers $headers -UseBasicParsing } if ($Method -eq 'DELETE') diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureVerifiedIdFaceCheck/MSFT_AzureVerifiedIdFaceCheck.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureVerifiedIdFaceCheck/MSFT_AzureVerifiedIdFaceCheck.psm1 index 467f46d674..c42db507fd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AzureVerifiedIdFaceCheck/MSFT_AzureVerifiedIdFaceCheck.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AzureVerifiedIdFaceCheck/MSFT_AzureVerifiedIdFaceCheck.psm1 @@ -345,7 +345,7 @@ function Export-TargetResource Authorization = (Get-MSCloudLoginConnectionProfile -Workload AdminAPI).AccessToken } $uri = 'https://verifiedid.did.msidentity.com/v1.0/verifiableCredentials/authorities' - $response = Invoke-WebRequest -Uri $uri -Method Get -Headers $headers + $response = Invoke-WebRequest -Uri $uri -Method Get -Headers $headers -UseBasicParsing $authorities = ConvertFrom-Json $response.Content $resourceGroups = Get-AzResourceGroup -ErrorAction Stop diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderDeviceAuthenticatedScanDefinition/MSFT_DefenderDeviceAuthenticatedScanDefinition.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderDeviceAuthenticatedScanDefinition/MSFT_DefenderDeviceAuthenticatedScanDefinition.psm1 index 70b2391927..0c3135890c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderDeviceAuthenticatedScanDefinition/MSFT_DefenderDeviceAuthenticatedScanDefinition.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_DefenderDeviceAuthenticatedScanDefinition/MSFT_DefenderDeviceAuthenticatedScanDefinition.psm1 @@ -146,8 +146,8 @@ function Get-TargetResource else { $ScanAuthenticationParamsValue = @{ - '@odata.context' = '#microsoft.windowsDefenderATP.api.SnmpAuthParams' - Type = 'NoAuthNoPriv' + DataType = '#microsoft.windowsDefenderATP.api.SnmpAuthParams' + Type = 'NoAuthNoPriv' } } diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index abcf010e69..7e41f762f2 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-12-18 +# Generated on: 2025-01-08 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.1218.1' + ModuleVersion = '1.25.108.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -147,25 +147,20 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* AADApplication - * Added support for Oauth2PermissionScopes. - * Fixes comparison issue for permissions. -* EXOTransportRule - * Fixes issue extracting arrays in Get-TargetResource. - * FIXES [#5575](https://github.com/microsoft/Microsoft365DSC/issues/5575) -* TeamsMeetingPolicy - * Adds support for additional Copilot setting value. - * FIXES [#5573](https://github.com/microsoft/Microsoft365DSC/issues/5573) - * FIXES [#5550](https://github.com/microsoft/Microsoft365DSC/issues/5550) + ReleaseNotes = '* AADAuthenticationRequirement + * Changed Export logic to extract instances from all users. +* AADOrganizationCertificateBasedAuthConfiguration + * Fixed the primary key of the resource. + FIXES [#5523](https://github.com/microsoft/Microsoft365DSC/issues/5523) +* AADRoleEligibilityScheduleRequest + * Fixed error when extracting an entry with a deleted principal. +* DefenderDeviceAuthenticatedScanDefinition + * Fixed the Data Type export. * MISC - * Fixed the Fabric web request to use basic parsing. - * Reset only necessary authentication context. -* M365DSCUtil - * Update `Get-M365DSCWorkloadsListFromResourceNames` function for more input types. - FIXES [#5525](https://github.com/microsoft/Microsoft365DSC/issues/5525) -* DEPENDENCIES - * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.202. - * Updated MSCloudLoginAssistant to version 1.1.31.' + * Added check to `New-M365DSCReportFromConfiguration` to make sure Windows + Remoting is enabled, which is required to convert the DSC config. + * Defender + * Added support for the UseBasicParsing parameter for REST calls.' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index 1ecbbefb85..50d924d40c 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -722,22 +722,29 @@ function New-M365DSCReportFromConfiguration } process # required with DynamicParam { - + # Test if Windows Remoting is enabled, which is needed to run this function. + $result = Test-WSMan -ErrorAction SilentlyContinue + if ($null -eq $result) + { + Write-Error -Message 'Windows Remoting is NOT configured yet. Please configure Windows Remoting (by running `Enable-PSRemoting -SkipNetworkProfileCheck`) before running this function.' + return + } + # Validate that the latest version of the module is installed. Test-M365DSCModuleValidity - + #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies - + #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Event', 'Report') $data.Add('Type', $Type) Add-M365DSCTelemetryEvent -Data $data -Type 'NewReport' #endregion - + [Array] $parsedContent = Initialize-M365DSCReporting -ConfigurationPath $ConfigurationPath - + if ($null -ne $parsedContent) { switch ($Type) diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCDefenderHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCDefenderHelper.psm1 index df62ffcf32..c677bfaeb1 100644 --- a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCDefenderHelper.psm1 +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCDefenderHelper.psm1 @@ -24,7 +24,8 @@ function Invoke-M365DSCDefenderREST $response = Invoke-WebRequest -Method $Method ` -Uri $Uri ` -Headers $headers ` - -Body $bodyJSON + -Body $bodyJSON ` + -UseBasicParsing $result = ConvertFrom-Json $response.Content return $result } diff --git a/docs/docs/user-guide/get-started/how-to-install.md b/docs/docs/user-guide/get-started/how-to-install.md index df0f8f21b1..c15e403c35 100644 --- a/docs/docs/user-guide/get-started/how-to-install.md +++ b/docs/docs/user-guide/get-started/how-to-install.md @@ -15,7 +15,7 @@ Executing this command can take a minute or two to complete, after which the bas ## Dependencies -However, Microsoft365DSC depends on several other modules to function properly. For example, it uses the MSCloudLoginAssistant module to delegate all authentication logic to the various workloads, it leverages a dozen Microsoft Graph PowerShell modules to interact with various configuration settings, etc. Current versions of Microsoft365DSC no longer download all the required prerequisites by default. When you install the Microsoft365DSC, you only get the core component after which you have to download all prerequisite modules as well. It is our recommendation that you run the following command to update all dependencies on the system after installing the module: +However, Microsoft365DSC depends on several other modules to function properly. For example, it uses the MSCloudLoginAssistant module to delegate all authentication logic to the various workloads, it leverages a dozen Microsoft Graph PowerShell modules to interact with various configuration settings, etc. Current versions of Microsoft365DSC no longer download all the required prerequisites by default. When you install the Microsoft365DSC module, you only get the core component after which you have to download all prerequisite modules as well. It is our recommendation that you run the following command to update all dependencies on the system after installing the module: ```PowerShell Update-M365DSCDependencies @@ -41,11 +41,10 @@ Get-Module Microsoft365DSC -ListAvailable | select ModuleBase, Version ## Updating To A Newer Version -To update an older version of Microsoft365DSC, use the **Update-Module** cmdlet and run the **Update-M365DSCDependencies** cmdlet again to update any dependencies. +To update an older version of Microsoft365DSC, use the **Update-M365DSCModule** cmdlet. This will update the current version of Microsoft365DSC and all dependencies in one go as well as uninstalling all outdated versions. ```PowerShell -Update-Module Microsoft365DSC -Update-M365DSCDependencies +Update-M365DSCModule ``` ## More Information @@ -55,7 +54,7 @@ More information about installing modules: - Installing a PowerShell module - Find-Module cmdlet - Install-Module cmdlet -- Update-Module cmdlet +- Update-M365DSCModule cmdlet - Save-Module cmdlet - About PSModulePath diff --git a/docs/docs/user-guide/get-started/troubleshooting.md b/docs/docs/user-guide/get-started/troubleshooting.md index f974c666ae..5ace1769bd 100644 --- a/docs/docs/user-guide/get-started/troubleshooting.md +++ b/docs/docs/user-guide/get-started/troubleshooting.md @@ -64,3 +64,28 @@ Optionally, for improved performance, you can increase the handles and threads p $quotaConfiguration.HandlesPerHost = 8192 $quotaConfiguration.ThreadsPerHost = 512 ``` + + +## Error "InvalidOperation: Cannot index into a null array" when creating a report from configuration + +### ISSUE + +When creating a report from either running `New-M365DSCDeltaReport` or `New-M365DSCReportFromConfiguration`, you might receive the following error and the generated report is empty: + +```powershell +Cannot index into a null array. +At C:\Program Files\WindowsPowerShell\Modules\DSCParser\2.0.0.5\Modules\DSCParser.psm1:**456** char:9 ++ $resourceType = $resource.CommandElements[0].Value ++ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + CategoryInfo : InvalidOperation: (:) [], RuntimeException + + FullyQualifiedErrorId : NullArray +``` + +### CAUSE + +This issue might occur if there are multiple versions of Microsoft365DSC present on the current machine and the configuration contains nested objects. +The nested objects are resolved from their CIM definitions, and if multiple versions of Microsoft365DSC are present, multiple versions of these CIM definitions exist. + +### RESOLUTION + +Update and install to the latest supported version of Microsoft365DSC using `Update-M365DSCModule`. This will uninstall all outdated versions and dependencies and update to the latest version available on the PowerShell Gallery. \ No newline at end of file