From ccabc5458c43fe1c22571f8aeae609ae5bc99cd0 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 30 Nov 2023 12:14:23 -0500 Subject: [PATCH] Various Fixes --- CHANGELOG.md | 47 ++-- .../MSFT_AADAttributeSet.psm1 | 12 +- .../MSFT_AADAttributeSet/settings.json | 4 +- ...SFT_AADRoleEligibilityScheduleRequest.psm1 | 34 ++- .../MSFT_IntuneDeviceCleanupRule.psm1 | 3 +- .../MSFT_IntunePolicySets.psm1 | 20 +- .../MSFT_M365DSCRuleEvaluation.psm1 | 1 + .../Modules/M365DSCReverse.psm1 | 36 ++- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 212 +++++++++--------- 9 files changed, 219 insertions(+), 150 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 830057e90c..df0ce3685e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,18 @@ # UNRELEASED -* IntuneAntivirusPolicyWindows10SettingCatalog - * Skipped settingValueTemplateReference and settingInstanceTemplateReference for severethreats, highseveritythreats, moderateseveritythreats, lowseveritythreats as per API requirements observed in the Intune portal - FIXES [#3818](https://github.com/microsoft/Microsoft365DSC/issues/3818) - FIXES [#3955](https://github.com/microsoft/Microsoft365DSC/issues/3955) * AADRoleSetting * Export sorted by DisplayName for better comparison * Enable Filter property to be used on export FIXES [#3919](https://github.com/microsoft/Microsoft365DSC/issues/3919) +* AADUser + * Added the MemberOf Property. +* IntuneAntivirusPolicyWindows10SettingCatalog + * Skipped settingValueTemplateReference and settingInstanceTemplateReference + for severethreats, highseveritythreats, moderateseveritythreats, + lowseveritythreats as per API requirements observed in the Intune portal. + FIXES [#3818](https://github.com/microsoft/Microsoft365DSC/issues/3818) + FIXES [#3955](https://github.com/microsoft/Microsoft365DSC/issues/3955) * IntuneAccountProtectionLocalAdministratorPasswordSolutionPolicy, IntuneAccountProtectionLocalUserGroupMembershipPolicy, IntuneAccountProtectionPolicy, @@ -24,36 +28,37 @@ IntuneWindowsAutopilotDeploymentProfileAzureADHybridJoined, IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Removed Id and all authentication parameters from PSBoundParameters in Test-TargetResource - FIXES [#3888](https://github.com/microsoft/Microsoft365DSC/issues/3888) -* DEPENDENCIES - * Updated DSCParser to version 1.4.0.1. - * Updated Microsoft.Graph to version 2.10.0. - * Updated MSCloudLoginAssistant to version 1.1.0. -* TeamsTeam - * Fixes incompatible type for ComplianceRecordingApplications, expected string[] but receive object[] - FIXES: [#3890](https://github.com/microsoft/Microsoft365DSC/issues/3890) -* M365DSCDRGUtil - * Added ConvertFrom-IntunePolicyAssignment and ConvertTo-IntunePolicyAssignment - FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) + FIXES [#3888](https://github.com/microsoft/Microsoft365DSC/issues/3888) * IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Modified assigned to use sdk instead of API call and added logic to use groupDisplayName in assignment - FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) + FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) * IntuneDeviceEnrollmentStatusPageWindows10 * Fixed assignments using API call - FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) + FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) * IntuneWindowsAutopilotDeploymentProfileAzureADHybridJoined * Modified assigned to use sdk instead of API call and added logic to use groupDisplayName in assignment - FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) + FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) * IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Modified assigned to use sdk instead of API call and added logic to use groupDisplayName in assignment - FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) + FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) * IntuneWindowsUpdateForBusinessRingUpdateProfileWindows10 * Modified assigned to use sdk instead of API call and added logic to use groupDisplayName in assignment * IntuneDeviceConfigurationPolicyWindows10 - FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) + FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) * IntuneDeviceEnrollmentStatusPageWindows10 * Fixed assignments using API call - FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) + FIXES [#3921](https://github.com/microsoft/Microsoft365DSC/issues/3921) +* TeamsTeam + * Fixes incompatible type for ComplianceRecordingApplications, expected string[] but receive object[] + FIXES: [#3890](https://github.com/microsoft/Microsoft365DSC/issues/3890) +* DEPENDENCIES + * Updated DSCParser to version 1.4.0.1. + * Updated Microsoft.Graph to version 2.10.0. + * Updated MSCloudLoginAssistant to version 1.1.0. +* MISC + * M365DSCDRGUtil + * Added ConvertFrom-IntunePolicyAssignment and ConvertTo-IntunePolicyAssignment + FIXES [#3892](https://github.com/microsoft/Microsoft365DSC/issues/3892) # 1.23.1122.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/MSFT_AADAttributeSet.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/MSFT_AADAttributeSet.psm1 index 47173e12ac..e7f4611617 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/MSFT_AADAttributeSet.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/MSFT_AADAttributeSet.psm1 @@ -363,13 +363,19 @@ function Export-TargetResource } catch { - Write-Host $Global:M365DSCEmojiRedX - - New-M365DSCLogEntry -Message 'Error during Export:' ` + if ($_.ErrorDetails.Message -like "*Insufficient privileges*") + { + Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle) Insufficient permissions or license to export Attribute Sets." + } + else + { + Write-Host $Global:M365DSCEmojiRedX + New-M365DSCLogEntry -Message 'Error during Export:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + } return '' } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/settings.json index 9d211172e0..227706211e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAttributeSet/settings.json @@ -3,10 +3,10 @@ "description": "Represents a group of related custom security attribute definitions.", "roles": { "read": [ - "Security Reader" + "Attribute Definition Reader" ], "update": [ - "Authentication Policy Administrator" + "Attribute Definition Administrator" ] }, "permissions": { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 index 75a152c5a8..6e1e50dcaa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 @@ -188,6 +188,14 @@ } if ($null -eq $schedule -or $null -eq $request) { + if ($null -eq $schedule) + { + Write-Verbose -Message "Could not retrieve the schedule for {$($request.PrincipalId)} & RoleDefinitionId {$RoleDefinitionId}" + } + if ($null -eq $request) + { + Write-Verbose -Message "Could not request the schedule for {$RoleDefinition}" + } return $nullResult } @@ -211,6 +219,7 @@ if ($null -eq $PrincipalInstance) { + Write-Verbose -Message "Couldn't retrieve Principal {$($request.PrincipalId)}" return $nullResult } @@ -298,7 +307,7 @@ } catch { - Write-Verbose "Verbose: $($_.ErrorDetails.Message)" + Write-Verbose "Error: $($_.ErrorDetails.Message)" New-M365DSCLogEntry -Message 'Error retrieving data:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` @@ -814,15 +823,20 @@ function Export-TargetResource } catch { - Write-Verbose -Message "Exception: $($_.Exception.Message)" - - Write-Host $Global:M365DSCEmojiRedX - - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + if ($_.ErrorDetails.Message -like "*The tenant needs an AAD Premium*") + { + Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle) Tenant does not meet license requirement to extract this component." + } + else + { + Write-Verbose -Message "Exception: $($_.Exception.Message)" + Write-Host $Global:M365DSCEmojiRedX + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } return '' } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCleanupRule/MSFT_IntuneDeviceCleanupRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCleanupRule/MSFT_IntuneDeviceCleanupRule.psm1 index f60d059e3f..a37c05d228 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCleanupRule/MSFT_IntuneDeviceCleanupRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCleanupRule/MSFT_IntuneDeviceCleanupRule.psm1 @@ -376,7 +376,8 @@ function Export-TargetResource } catch { - if ($_.Exception -like '*401*' -or $_.ErrorDetails.Message -like "*`"ErrorCode`":`"Forbidden`"*") + if ($_.Exception -like "*401*" -or $_.ErrorDetails.Message -like "*`"ErrorCode`":`"Forbidden`"*" -or + $_.Exception -like "* Unauthorized*") { Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle) The current tenant is not registered for Intune." } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntunePolicySets/MSFT_IntunePolicySets.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntunePolicySets/MSFT_IntunePolicySets.psm1 index adcdbc45b6..e33eab8210 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntunePolicySets/MSFT_IntunePolicySets.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntunePolicySets/MSFT_IntunePolicySets.psm1 @@ -656,13 +656,21 @@ function Export-TargetResource } catch { - Write-Host $Global:M365DSCEmojiRedX + if ($_.Exception -like "*401*" -or $_.ErrorDetails.Message -like "*`"ErrorCode`":`"Forbidden`"*" -or + $_.Exception -like "* Unauthorized*") + { + Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle) The current tenant is not registered for Intune." + } + else + { + Write-Host $Global:M365DSCEmojiRedX - New-M365DSCLogEntry -Message 'Error during Export:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + } return '' } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_M365DSCRuleEvaluation/MSFT_M365DSCRuleEvaluation.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_M365DSCRuleEvaluation/MSFT_M365DSCRuleEvaluation.psm1 index 793817f0af..01a227e082 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_M365DSCRuleEvaluation/MSFT_M365DSCRuleEvaluation.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_M365DSCRuleEvaluation/MSFT_M365DSCRuleEvaluation.psm1 @@ -289,6 +289,7 @@ function Export-TargetResource [Switch] $ManagedIdentity ) + Write-Host "`r`n" -NoNewline return $null } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 index 7c3d9e9d6d..f9e589b770 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 @@ -146,6 +146,13 @@ function Start-M365DSCConfigurationExtract Write-Host -Object '- Credentials' $AuthMethods += 'Credentials' } + if ($null -ne $Credential -and ` + [System.String]::IsNullOrEmpty($ApplicationId) -and ` + -not [System.String]::IsNullOrEmpty($TenantId)) + { + Write-Host -Object '- Credentials with Tenant Id' + $AuthMethods += 'CredentialsWithTenantId' + } if ($null -ne $Credential -and ` -not [System.String]::IsNullOrEmpty($ApplicationId)) { @@ -232,7 +239,7 @@ function Start-M365DSCConfigurationExtract Write-Host '[WARNING]' -NoNewline -ForegroundColor Yellow Write-Host ' Based on the provided Authentication parameters, the following resources cannot be extracted: ' -ForegroundColor Gray - Write-Host "$resourcesNotSupported" -ForegroundColor Gray + Write-Host "$($resourcesNotSupported -join ',')" -ForegroundColor Gray # If all selected resources are not valid based on the authentication method used, simply return. if ($ComponentsToSkip.Length -eq $selectedResources.Length) @@ -409,7 +416,7 @@ function Start-M365DSCConfigurationExtract -Value $ApplicationSecret ` -Description 'Azure AD Application Secret for Authentication' } - { $_ -in 'Credentials', 'CredentialsWithApplicationId' } + { $_ -in 'Credentials', 'CredentialsWithApplicationId', 'CredentialsWithTenantId' } { if ($newline) { @@ -485,9 +492,15 @@ function Start-M365DSCConfigurationExtract if ((($Components -and ($Components -contains $resourceName)) -or $AllComponents -or ` (-not $Components -and $null -eq $Workloads)) -and ` ($ComponentsSpecified -or ($ComponentsToSkip -notcontains $resourceName)) -and ` - $resourcesNotSupported -notcontains $resourceName) + $resourcesNotSupported -notcontains $resourceName -and ` + -not $resourceName.StartsWith("M365DSC")) { - $ResourcesToExport += $ResourceName + $authMethod = $allSupportedResourcesWithMostSecureAuthMethod | Where-Object -FilterScript {$_.Resource -eq $ResourceName} + $resourceInfo = @{ + Name = $ResourceName + AuthenticationMethod = $authMethod.AuthMethod + } + $ResourcesToExport += $resourceInfo $ResourcesPath += $ResourceModule } } @@ -506,9 +519,9 @@ function Start-M365DSCConfigurationExtract } foreach ($Workload in $WorkloadsToConnectTo) { - Write-Host "Connecting to {$Workload}..." -NoNewline + Write-Host "Connecting to {$($Workload.Name)}..." -NoNewline $ConnectionParams = @{ - Workload = $Workload + Workload = $Workload.Name ApplicationId = $ApplicationId ApplicationSecret = $ApplicationSecret TenantId = $TenantId @@ -519,6 +532,12 @@ function Start-M365DSCConfigurationExtract Identity = $ManagedIdentity.IsPresent } + if ($workload.AuthenticationMethod -eq 'Credentials') + { + $ConnectionParams.Remove('TenantId') | Out-Null + $ConnectionParams.Remove('ApplicationId') | Out-Null + } + try { Connect-M365Tenant @ConnectionParams | Out-Null @@ -570,6 +589,11 @@ function Start-M365DSCConfigurationExtract } $parameters.Add('Credential', $Credential) } + 'CredentialsWithTenantId' + { + $parameters.Add('Credential', $Credential) + $parameters.Add('TenantId', $TenantId) + } 'ManagedIdentity' { $parameters.Add('ManagedIdentity', $ManagedIdentity) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 673407432a..acd30fb124 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1216,14 +1216,6 @@ function Export-M365DSCConfiguration return } - if ($PSBoundParameters.ContainsKey('ApplicationId') -eq $false -and ` - $ManagedIdentity.IsPresent -eq $false -and ` - $PSBoundParameters.ContainsKey('TenantId') -eq $true) - { - Write-Host -Object '[ERROR] You have to specify ApplicationId when you specify TenantId' -ForegroundColor Red - return - } - if ($PSBoundParameters.ContainsKey('ApplicationId') -eq $true -and ` $PSBoundParameters.ContainsKey('TenantId') -eq $true -and ` ($PSBoundParameters.ContainsKey('CertificateThumbprint') -eq $false -and ` @@ -1712,14 +1704,13 @@ function New-M365DSCConnection # Case both authentication methods are attempted if ($null -ne $InboundParameters.Credential -and ` - (-not [System.String]::IsNullOrEmpty($InboundParameters.TenantId) -or ` - -not [System.String]::IsNullOrEmpty($InboundParameters.CertificateThumbprint))) + -not [System.String]::IsNullOrEmpty($InboundParameters.CertificateThumbprint)) { $message = 'Both Authentication methods are attempted' Write-Verbose -Message $message $data.Add('Event', 'Error') $data.Add('Exception', $message) - $errorText = "You can't specify both the Credential and one of {TenantId, CertificateThumbprint}" + $errorText = "You can't specify both the Credential and CertificateThumbprint" $data.Add('CustomMessage', $errorText) Add-M365DSCTelemetryEvent -Type 'Error' -Data $data throw $errorText @@ -1865,22 +1856,8 @@ function New-M365DSCConnection } #endregion - # Case both authentication methods are attempted - if ($null -ne $InboundParameters.Credential -and ` - (-not [System.String]::IsNullOrEmpty($InboundParameters.TenantId) -or ` - -not [System.String]::IsNullOrEmpty($InboundParameters.CertificateThumbprint))) - { - $message = 'Both Authentication methods are attempted' - Write-Verbose -Message $message - $data.Add('Event', 'Error') - $data.Add('Exception', $message) - $errorText = "You can't specify both the Credential and one of {TenantId, CertificateThumbprint}" - $data.Add('CustomMessage', $errorText) - Add-M365DSCTelemetryEvent -Type 'Error' -Data $data - throw $errorText - } # Case no authentication method is specified - elseif ($null -eq $InboundParameters.Credential -and ` + if ($null -eq $InboundParameters.Credential -and ` [System.String]::IsNullOrEmpty($InboundParameters.ApplicationId) -and ` [System.String]::IsNullOrEmpty($InboundParameters.TenantId) -and ` [System.String]::IsNullOrEmpty($InboundParameters.CertificateThumbprint)) @@ -1895,58 +1872,14 @@ function New-M365DSCConnection Add-M365DSCTelemetryEvent -Type 'Error' -Data $data throw $errorText } - # Case only Credential is specified - elseif ($null -ne $InboundParameters.Credential -and ` - [System.String]::IsNullOrEmpty($InboundParameters.ApplicationId) -and ` - [System.String]::IsNullOrEmpty($InboundParameters.TenantId) -and ` - [System.String]::IsNullOrEmpty($InboundParameters.CertificateThumbprint)) + else { - Write-Verbose -Message 'Credential was specified. Connecting via User Principal' - if ([System.String]::IsNullOrEmpty($Url)) - { - Connect-M365Tenant -Workload $Platform ` - -Credential $InboundParameters.Credential ` - -SkipModuleReload $Global:CurrentModeIsExport - } - else - { - Connect-M365Tenant -Workload $Platform ` - -Credential $InboundParameters.Credential ` - -ConnectionUrl $Url ` - -SkipModuleReload $Global:CurrentModeIsExport - } - - $data.Add('ConnectionType', 'Credential') - try - { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) - } - catch - { - Write-Verbose -Message $_ - } + $data.Add('ConnectionType', 'ServicePrincipalWithPath') + $data.Add('Tenant', $InboundParameters.TenantId) Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' - return 'Credentials' - } - # Case only the ApplicationID and Credentials parameters are specified - elseif ($null -ne $InboundParameters.Credential -and ` - -not [System.String]::IsNullOrEmpty($InboundParameters.ApplicationId)) - { - Connect-M365Tenant -Workload $Workload ` - -ApplicationId $InboundParameters.ApplicationId ` - -TenantId $InboundParameters.TenantId ` - -CertificatePassword $InboundParameters.CertificatePassword.Password ` - -CertificatePath $InboundParameters.CertificatePath ` - -Url $Url ` - -SkipModuleReload $Global:CurrentModeIsExport + return 'ServicePrincipalWithPath' } - $data.Add('ConnectionType', 'ServicePrincipalWithPath') - $data.Add('Tenant', $InboundParameters.TenantId) - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' - - return 'ServicePrincipalWithPath' } # Case only the ApplicationSecret, TenantId and ApplicationID are specified elseif ($null -eq $InboundParameters.Credential -and ` @@ -2000,6 +1933,17 @@ function New-M365DSCConnection Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithThumbprint' } + # Case only the TenantId and Credentials parameters are specified + elseif ($null -ne $InboundParameters.Credential -and ` + -not [System.String]::IsNullOrEmpty($InboundParameters.TenantId)) + { + Connect-M365Tenant -Workload $Workload ` + -TenantId $InboundParameters.TenantId ` + -Credential $InboundParameters.Credential ` + -Url $Url ` + -SkipModuleReload $Global:CurrentModeIsExport + return "CredentialsWithTenantId" + } # Case only Managed Identity and TenantId are specified elseif ($InboundParameters.ManagedIdentity -and ` -not [System.String]::IsNullOrEmpty($InboundParameters.TenantId)) @@ -3062,7 +3006,7 @@ function Update-M365DSCExportAuthenticationResults ( [Parameter(Mandatory = $true)] [System.String] - [ValidateSet('ServicePrincipalWithThumbprint', 'ServicePrincipalWithSecret', 'ServicePrincipalWithPath', 'CredentialsWithApplicationId', 'Credentials', 'ManagedIdentity')] + [ValidateSet('ServicePrincipalWithThumbprint', 'ServicePrincipalWithSecret', 'ServicePrincipalWithPath', 'CredentialsWithTenantId', 'CredentialsWithApplicationId', 'Credentials', 'ManagedIdentity')] $ConnectionMode, [Parameter(Mandatory = $true)] @@ -3102,6 +3046,30 @@ function Update-M365DSCExportAuthenticationResults $Results.Remove('CertificatePassword') | Out-Null } } + elseif ($ConnectionMode -eq 'CredentialsWithTenantId') + { + $Results.Credential = Resolve-Credentials -UserName 'credential' + if ($Results.ContainsKey('ApplicationId')) + { + $Results.Remove('ApplicationId') | Out-Null + } + if ($Results.ContainsKey('ApplicationSecret')) + { + $Results.Remove('ApplicationSecret') | Out-Null + } + if ($Results.ContainsKey('CertificateThumbprint')) + { + $Results.Remove('CertificateThumbprint') | Out-Null + } + if ($Results.ContainsKey('CertificatePath')) + { + $Results.Remove('CertificatePath') | Out-Null + } + if ($Results.ContainsKey('CertificatePassword')) + { + $Results.Remove('CertificatePassword') | Out-Null + } + } else { if ($Results.ContainsKey('Credential') -and $ConnectionMode -ne 'CredentialsWithApplicationId') @@ -3225,7 +3193,7 @@ function Get-M365DSCExportContentForResource [Parameter(Mandatory = $true)] [System.String] - [ValidateSet('ServicePrincipalWithThumbprint', 'ServicePrincipalWithSecret', 'ServicePrincipalWithPath', 'CredentialsWithApplicationId', 'Credentials', 'ManagedIdentity')] + [ValidateSet('ServicePrincipalWithThumbprint', 'ServicePrincipalWithSecret', 'ServicePrincipalWithPath', 'CredentialsWithTenantId', 'CredentialsWithApplicationId', 'Credentials', 'ManagedIdentity')] $ConnectionMode, [Parameter(Mandatory = $true)] @@ -3470,7 +3438,7 @@ function Get-M365DSCComponentsWithMostSecureAuthenticationType ( [Parameter()] [System.String[]] - [ValidateSet('ApplicationWithSecret', 'CertificateThumbprint', 'CertificatePath', 'Credentials', 'CredentialsWithApplicationId', 'ManagedIdentity')] + [ValidateSet('ApplicationWithSecret', 'CertificateThumbprint', 'CertificatePath', 'Credentials', 'CredentialsWithTenantId', 'CredentialsWithApplicationId', 'ManagedIdentity')] $AuthenticationMethod, [Parameter()] @@ -3522,6 +3490,18 @@ function Get-M365DSCComponentsWithMostSecureAuthenticationType AuthMethod = 'ApplicationSecret' } } + # Case - Resource supports CredentialWithTenantId + elseif ($AuthenticationMethod.Contains('CredentialsWithTenantId') -and ` + $parameters.Contains('Credential') -and $parameters.Contains('TenantId') -and ` + -not $resource.Name.StartsWith('MSFT_SPO') -and ` + -not $resource.Name.StartsWith('MSFT_OD') -and ` + -not $resource.Name.StartsWith('MSFT_PP')) + { + $Components += @{ + Resource = $resource.Name -replace 'MSFT_', '' -replace '.psm1', '' + AuthMethod = 'CredentialsWithTenantId' + } + } # Case - Resource supports Credential using CredentialsWithApplicationId elseif ($AuthenticationMethod.Contains('CredentialsWithApplicationId') -and ` $parameters.Contains('Credential')) @@ -3628,89 +3608,119 @@ Public function Get-M365DSCWorkloadsListFromResourceNames { [CmdletBinding()] - [OutputType([System.Boolean])] + [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true, Position = 1)] - [String[]] + [System.Array] $ResourceNames ) [Array] $workloads = @() foreach ($resource in $ResourceNames) { - switch ($resource.Substring(0, 2).ToUpper()) + switch ($resource.Name.Substring(0, 2).ToUpper()) { 'AA' { - if (-not $workloads.Contains('MicrosoftGraph')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph')) { - $workloads += 'MicrosoftGraph' + $workloads += @{ + Name = 'MicrosoftGraph' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'EX' { - if (-not $workloads.Contains('ExchangeOnline')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('ExchangeOnline')) { - $workloads += 'ExchangeOnline' + $workloads += @{ + Name = 'ExchangeOnline' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'In' { - if (-not $workloads.Contains('MicrosoftGraph')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph')) { - $workloads += 'MicrosoftGraph' + $workloads += @{ + Name = 'MicrosoftGraph' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'O3' { - if (-not $workloads.Contains('MicrosoftGraph') -and $resource -eq 'O365Group') + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph') -and $resource -eq 'O365Group') { - $workloads += 'MicrosoftGraph' + $workloads += @{ + Name = 'MicrosoftGraph' + AuthenticationMethod = $resource.AuthenticationMethod + } } - elseif (-not $workloads.Contains('ExchangeOnline')) + elseif (-not $workloads.Name -or -not $workloads.Name.Contains('ExchangeOnline')) { - $workloads += 'ExchangeOnline' + $workloads += @{ + Name = 'ExchangeOnline' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'OD' { - if (-not $workloads.Contains('PnP')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('PnP')) { - $workloads += 'PnP' + $workloads += @{ + Name = 'PnP' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'Pl' { - if (-not $workloads.Contains('MicrosoftGraph')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftGraph')) { - $workloads += 'MicrosoftGraph' + $workloads += @{ + Name = 'MicrosoftGraph' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'SP' { - if (-not $workloads.Contains('PnP')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('PnP')) { - $workloads += 'PnP' + $workloads += @{ + Name = 'PnP' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'SC' { - if (-not $workloads.Contains('SecurityComplianceCenter')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('SecurityComplianceCenter')) { - $workloads += 'SecurityComplianceCenter' + $workloads += @{ + Name = 'SecurityComplianceCenter' + AuthenticationMethod = $resource.AuthenticationMethod + } } } 'Te' { - if (-not $workloads.Contains('MicrosoftTeams')) + if (-not $workloads.Name -or -not $workloads.Name.Contains('MicrosoftTeams')) { - $workloads += 'MicrosoftTeams' + $workloads += @{ + Name = 'MicrosoftTeams' + AuthenticationMethod = $resource.AuthenticationMethod + } } } } } - return ($workloads | Sort-Object) + return ($workloads | Sort-Object {$_.Name}) } <#