From ab827f2957b4899c63300ccd58af3055c8a91f01 Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Fri, 1 Dec 2023 07:40:34 +0100 Subject: [PATCH 001/171] IntuneSettingCatalogASRRulesPolicyWindows10: Fixed Schema Validation with parameter Identity made Mandatory --- CHANGELOG.md | 3 +++ .../MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 830057e90c..848b88e82b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # UNRELEASED +* IntuneSettingCatalogASRRulesPolicyWindows10 + * Fixed Schema Validation with parameter Identity made Mandatory + FIXES [#3961](https://github.com/microsoft/Microsoft365DSC/issues/3961) * 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) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index a059ab3082..988978add4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -4,7 +4,7 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, @@ -283,7 +283,7 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, @@ -540,7 +540,7 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, From fc6d98e8c71b1d1f297fee4127ff9cb0327e76ce Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Fri, 1 Dec 2023 07:51:06 +0100 Subject: [PATCH 002/171] update changelog --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 256147b6c0..a484897505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,26 +34,26 @@ IntuneWindowsAutopilotDeploymentProfileAzureADHybridJoined, IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Removed Id and all authentication parameters from PSBoundParameters in Test-TargetResource - FIXES [#3888](https://github.com/microsoft/Microsoft365DSC/issues/3888) + 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) * TeamsMessagingPolicy * Added support for properties AllowCommunicationComplianceEndUserReporting, AllowFluidCollaborate and AllowSecurityEndUserReporting. From 314a3239b9686d6f230a02f031315f8ecf7a99ec Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Fri, 1 Dec 2023 16:21:46 +0100 Subject: [PATCH 003/171] use M365DSCDRGUtil to fix ASRRulesPolicy --- ...SettingCatalogASRRulesPolicyWindows10.psm1 | 37 ++++++++++-------- ...gCatalogASRRulesPolicyWindows10.schema.mof | Bin 16772 -> 16776 bytes 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index 988978add4..894c62713b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -4,7 +4,7 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Identity, @@ -239,19 +239,8 @@ function Get-TargetResource } } - $returnAssignments = @() - $returnAssignments += Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $policy.Id - $assignmentResult = @() - foreach ($assignmentEntry in $returnAssignments) - { - $assignmentValue = @{ - dataType = $assignmentEntry.Target.AdditionalProperties.'@odata.type' - deviceAndAppManagementAssignmentFilterType = $assignmentEntry.Target.DeviceAndAppManagementAssignmentFilterType.toString() - deviceAndAppManagementAssignmentFilterId = $assignmentEntry.Target.DeviceAndAppManagementAssignmentFilterId - groupId = $assignmentEntry.Target.AdditionalProperties.groupId - } - $assignmentResult += $assignmentValue - } + $returnAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $policy.Id + $assignmentResult = ConvertFrom-IntunePolicyAssignment -Assignments $returnAssignments $returnHashtable.Add('Assignments', $assignmentResult) Write-Verbose -Message "Found Endpoint Protection Attack Surface Protection rules Policy {$($policy.name)}" @@ -283,7 +272,7 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Identity, @@ -490,8 +479,9 @@ function Set-TargetResource } if ($policy.id) { + $intuneAssignments = ConvertTo-IntunePolicyAssignment -Assignments $assignmentsHash Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` - -Targets $assignmentsHash + -Targets $intuneAssignments } #endregion } @@ -540,7 +530,7 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Identity, @@ -752,6 +742,19 @@ function Test-TargetResource $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment } + #GroupDisplayName Assignment + if (-not [String]::IsNullOrEmpty($assignment.groupDisplayName)) + { + $source = [Array]$ValuesToCheck.Assignments | Where-Object -FilterScript { $_.groupDisplayName -eq $assignment.groupDisplayName } + if (-not $source) + { + Write-Verbose -Message "Configuration drift: groupDisplayName {$($assignment.groupDisplayName)} not found" + $testResult = $false + break + } + $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment + } #AllDevices/AllUsers assignment else { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.schema.mof index 74aed24722b081a852f3482c8a4c1427b52617e6..84d1e0c2a4acdaa4c5ca8e4308157e886ffb908d 100644 GIT binary patch delta 22 ecmZo^X6$HY+)&3e`2xSjdlbKP&t`VOn&n+o<}ACU+D+I From c5cd2bf8baf8b671701f4c15dabbce0d2ad96996 Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Tue, 5 Dec 2023 09:28:34 +0100 Subject: [PATCH 004/171] fix error on getting policy by displayname & with empty assigments --- ...SettingCatalogASRRulesPolicyWindows10.psm1 | 22 +++++++++++++------ .../Modules/M365DSCDRGUtil.psm1 | 4 ++++ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index 894c62713b..e04ad2c1dc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -188,7 +188,7 @@ function Get-TargetResource if ($null -eq $policy) { Write-Verbose -Message "No Endpoint Protection Attack Surface Protection rules Policy {$Identity} was found" - $policy = Get-MgBetaDeviceManagementConfigurationPolicy | Where-Object -FilterScript { $_.Name -eq "$DisplayName" -and $_.templateReference.TemplateId -eq "$templateReferenceId" } -ErrorAction silentlyContinue + $policy = Get-MgBetaDeviceManagementConfigurationPolicy | Where-Object -FilterScript { $_.Name -eq "$DisplayName" -and $_.templateReference.TemplateId -eq "$templateReferenceId" } | Select-Object -First 1 } if ($null -eq $policy) @@ -240,7 +240,14 @@ function Get-TargetResource } $returnAssignments = Get-MgBetaDeviceManagementConfigurationPolicyAssignment -DeviceManagementConfigurationPolicyId $policy.Id - $assignmentResult = ConvertFrom-IntunePolicyAssignment -Assignments $returnAssignments + if ($returnAssignments.Count -gt 0) + { + $assignmentResult = ConvertFrom-IntunePolicyAssignment -Assignments $returnAssignments + } + else + { + $assignmentResult = @() + } $returnHashtable.Add('Assignments', $assignmentResult) Write-Verbose -Message "Found Endpoint Protection Attack Surface Protection rules Policy {$($policy.name)}" @@ -479,9 +486,9 @@ function Set-TargetResource } if ($policy.id) { - $intuneAssignments = ConvertTo-IntunePolicyAssignment -Assignments $assignmentsHash + $intuneAssignments = [Hashtable[]] (ConvertTo-IntunePolicyAssignment -Assignments $assignmentsHash) Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` - -Targets $intuneAssignments + -Targets ([Array]($intuneAssignments.target)) } #endregion } @@ -499,7 +506,7 @@ function Set-TargetResource #write-verbose -message ($settings|convertto-json -Depth 20) Update-IntuneDeviceConfigurationPolicy ` - -DeviceConfigurationPolicyId $Identity ` + -DeviceConfigurationPolicyId $currentPolicy.Identity ` -Name $DisplayName ` -Description $Description ` -TemplateReferenceId $templateReferenceId ` @@ -513,8 +520,9 @@ function Set-TargetResource { $assignmentsHash += Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignment } - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $Identity ` - -Targets $assignmentsHash + $intuneAssignments = [Hashtable[]] (ConvertTo-IntunePolicyAssignment -Assignments $assignmentsHash) + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $currentPolicy.Identity ` + -Targets ([Array]($intuneAssignments.target)) #endregion } elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') diff --git a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 index 307b4280a5..83667bea15 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCDRGUtil.psm1 @@ -1253,6 +1253,10 @@ function Update-DeviceConfigurationPolicyAssignment foreach ($target in $targets) { $formattedTarget = @{"@odata.type" = $target.dataType} + if(-not $formattedTarget."@odata.type" -and $target."@odata.type") + { + $formattedTarget."@odata.type" = $target."@odata.type" + } if ($target.groupId) { $formattedTarget.Add('groupId',$target.groupId) From fe8caef4e556033da446b5da667dbbde4caa1533 Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Tue, 5 Dec 2023 09:33:56 +0100 Subject: [PATCH 005/171] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d57a0a2119..611f5e5d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ # UNRELEASED * IntuneSettingCatalogASRRulesPolicyWindows10 - * Fixed Schema Validation with parameter Identity made Mandatory + * Fixed Schema Validation + * Fixed Import with unknown ID of Policy and Assignments by using DisplayName FIXES [#3961](https://github.com/microsoft/Microsoft365DSC/issues/3961) * DEPENDENCIES * Updated MSCloudLoginAssistant to version 1.1.1. From 553a617ee51475ea06d329c794938ec0600e5feb Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Mon, 11 Dec 2023 15:14:09 +0100 Subject: [PATCH 006/171] update schema --- ...gCatalogASRRulesPolicyWindows10.schema.mof | Bin 16776 -> 16766 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.schema.mof index 84d1e0c2a4acdaa4c5ca8e4308157e886ffb908d..bef985e88651981f825054989f14b4238bc5025e 100644 GIT binary patch delta 24 gcmeBZX8hO0xM2b>t2aX`L*-;fG5O8=cuyGv0BcJKO#lD@ delta 34 ocmey@#MsfyxM2b>e-J||Lm@*cLncEJkd-p|pqBjRExf0U0mKvwIRF3v From 9c0575938a58f5a5f0e201a33e79453ab3c3fa9d Mon Sep 17 00:00:00 2001 From: "ITACS\\mk" Date: Fri, 15 Dec 2023 09:10:14 +0100 Subject: [PATCH 007/171] throw Error instead of using the first found one --- .../MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index e04ad2c1dc..8ab4c12b0e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -188,7 +188,12 @@ function Get-TargetResource if ($null -eq $policy) { Write-Verbose -Message "No Endpoint Protection Attack Surface Protection rules Policy {$Identity} was found" - $policy = Get-MgBetaDeviceManagementConfigurationPolicy | Where-Object -FilterScript { $_.Name -eq "$DisplayName" -and $_.templateReference.TemplateId -eq "$templateReferenceId" } | Select-Object -First 1 + $policy = Get-MgBetaDeviceManagementConfigurationPolicy | Where-Object -FilterScript { $_.Name -eq "$DisplayName" -and $_.templateReference.TemplateId -eq "$templateReferenceId" } + + if ($policy.Count -gt 1) + { + throw "Multiple Endpoint Protection Attack Surface Protection rules Policies with DisplayName '{$DisplayName}' were found!" + } } if ($null -eq $policy) From a18f29d1173e83102e5a2c7111d3fad23ee637c9 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Sat, 30 Dec 2023 22:31:19 +0100 Subject: [PATCH 008/171] Added resource 'EXORecipientPermission' --- .../MSFT_EXORecipientPermission.psm1 | 473 ++++++++++++++++++ .../MSFT_EXORecipientPermission.schema.mof | 16 + .../MSFT_EXORecipientPermission/readme.md | 5 + .../MSFT_EXORecipientPermission/settings.json | 53 ++ .../1-EXORecipientPermission.ps1 | 30 ++ 5 files changed, 577 insertions(+) create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md create mode 100644 Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/settings.json create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 new file mode 100644 index 0000000000..399d1f64ac --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 @@ -0,0 +1,473 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $Identity, + + [Parameter(Mandatory = $true)] + [System.String] + $Trustee, + + [Parameter(Mandatory = $true)] + [ValidateSet('SendAs')] + [System.String[]] + $AccessRights, + + [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()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + + Write-Verbose -Message "Getting configuration of Office 365 Recipient permission $Identity" + if ($Script:ExportMode) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + + $nullReturn = $PSBoundParameters + $nullReturn.Ensure = 'Absent' + + try + { + + if ($null -ne $Script:recipientPermissions -and $Script:ExportMode) + { + $recipientPermission = $Script:recipientPermissions | Where-Object -FilterScript { + $_.Identity -eq $Identity -and $_.Trustee -eq $Trustee -and $_.AccessRights -eq $AccessRights + } + } + else + { + #Could include a switch for the different propertySets to retrieve https://learn.microsoft.com/en-us/powershell/exchange/cmdlet-property-sets?view=exchange-ps#get-exomailbox-property-sets + #Could include a switch for the different recipientTypeDetails to retrieve + $recipientPermission = Get-EXORecipientPermission -Identity $Identity -Trustee $Trustee -AccessRights $AccessRights -ErrorAction Stop + } + + if ($null -eq $recipientPermission) + { + Write-Verbose -Message "The specified Recipient Permission doesn't already exist." + return $nullReturn + } + + #endregion + + $result = @{ + Identity = $Identity + Trustee = $recipientPermission.Trustee + AccessRights = $recipientPermission.AccessRights + + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + } + + Write-Verbose -Message "Found an existing instance of Recipient permissions '$($DisplayName)'" + return $result + } + catch + { + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullReturn + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Trustee, + + [Parameter()] + [ValidateSet('SendAs')] + [System.String] + $AccessRights, + + [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()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + + Write-Verbose -Message "Setting Mail Contact configuration for $Name" + + $currentState = Get-TargetResource @PSBoundParameters + + if ($Global:CurrentModeIsExport) + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + } + else + { + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -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 + + $parameters = $PSBoundParameters + $parameters.Remove('Credential') | Out-Null + $parameters.Remove('ApplicationId') | Out-Null + $parameters.Remove('TenantId') | Out-Null + $parameters.Remove('CertificateThumbprint') | Out-Null + $parameters.Remove('CertificatePath') | Out-Null + $parameters.Remove('CertificatePassword') | Out-Null + $parameters.Remove('ManagedIdentity') | Out-Null + $parameters.Remove('Ensure') | Out-Null + + # Receipient Permission doesn't exist but it should + if ($Ensure -eq 'Present' -and $currentState.Ensure -eq 'Absent') + { + Write-Verbose -Message "The Receipient Permission for '$Trustee' with Access Rights '$($AccessRights -join ', ')' on mailbox '$Identity' does not exist but it should. Adding it." + Add-RecipientPermission @parameters -Confirm:$false + } + # Receipient Permission exists but shouldn't + elseif ($Ensure -eq 'Absent' -and $currentState.Ensure -eq 'Present') + { + Write-Verbose -Message "Receipient Permission for '$Trustee' with Access Rights '$($AccessRights -join ', ')' on mailbox '$Identity' exists but shouldn't. Removing it." + Remove-RecipientPermission @parameters -Confirm:$false + } + elseif ($Ensure -eq 'Present' -and $currentState.Ensure -eq 'Present') + { + Write-Verbose -Message "Receipient Permission for '$Trustee' with Access Rights '$($AccessRights -join ', ')' on mailbox '$Identity' exists." + } +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Trustee, + + [Parameter()] + [ValidateSet('SendAs')] + [System.String] + $AccessRights, + + [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()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message "Testing configuration of Office 365 Recipient permissions $DisplayName" + + $currentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $currentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $testResult = Test-M365DSCParameterState -CurrentValues $currentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck @('Ensure', 'Identity') + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $Identity, + + [Parameter()] + [System.String] + $Trustee, + + [Parameter()] + [ValidateSet('SendAs')] + [System.String] + $AccessRights, + + [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()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters ` + -SkipModuleReload $true + + #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:recipientPermissions = Get-EXORecipientPermission -ResultSize Unlimited + + $dscContent = '' + $i = 1 + if ($recipientPermissions.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($recipientPermission in $recipientPermissions) + { + Write-Host " |---[$i/$($recipientPermissions.Length)] $($recipientPermission.Identity)" -NoNewline + + $params = @{ + Identity = $recipientPermission.Identity + Trustee = $recipientPermission.Trustee + AccessRights = $recipientPermission.AccessRights + + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + } + + $Results = Get-TargetResource @Params + + if ($Results -is [System.Collections.Hashtable] -and $Results.Count -gt 1) + { + $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 + + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host $Global:M365DSCEmojiRedX + } + + $i++ + + } + 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_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof new file mode 100644 index 0000000000..40d874461b --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof @@ -0,0 +1,16 @@ +[ClassVersion("1.0.0.0"), FriendlyName("EXORecipientPermission")] +class MSFT_EXORecipientPermission : OMI_BaseResource +{ + [Write, Description("The mailbox the permission should be given on.")] String Identity; + [Write, Description("The account to give the permission to.")] String Trustee; + [Write, Description("The access rights granted to the account. Only 'SendAs' is supported.")] String AccessRights; + + [Write, Description("Present ensures the group exists, absent ensures it is removed"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; + [Write, Description("Credentials of the Exchange Global 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("Username can be made up to anything but password will be used for CertificatePassword"), EmbeddedInstance("MSFT_Credential")] String CertificatePassword; + [Write, Description("Path to certificate used in service principal usually a PFX file.")] String CertificatePath; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md new file mode 100644 index 0000000000..054863a71a --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md @@ -0,0 +1,5 @@ +# EXORecipientPermission + +## Description + +This resource allows users to retrieve Office 365 Recipient Permission. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/settings.json new file mode 100644 index 0000000000..4506c76525 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/settings.json @@ -0,0 +1,53 @@ +{ + "resourceName": "EXORecipientPermission", + "description": "", + "roles": { + "read": [ + "Global Reader" + ], + "update": [ + "Exchange Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Mail Enabled Public Folders", + "MyName", + "Public Folders", + "Compliance Admin", + "User Options", + "Message Tracking", + "View-Only Recipients", + "Role Management", + "Legal Hold", + "Audit Logs", + "Retention Management", + "Distribution Groups", + "Move Mailboxes", + "Information Rights Management", + "Mail Recipient Creation", + "Reset Password", + "View-Only Audit Logs", + "Mail Recipients", + "Mailbox Search", + "UM Mailboxes", + "Security Group Creation and Membership", + "Mailbox Import Export", + "MyMailboxDelegation", + "MyDisplayName" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 new file mode 100644 index 0000000000..c6d219bc54 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 @@ -0,0 +1,30 @@ + +<# +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(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXORecipientPermission 'AddSendAs' + { + + Identity = 'John' + Trustee = "admin@$OrganizationName" + AccessRights = 'SendAs' + Ensure = 'Present' + Credential = $Credscredential + } + } +} From 6012798fc1db8eb963681be16bb16216571880e3 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Thu, 4 Jan 2024 18:00:07 +0100 Subject: [PATCH 009/171] Added missing key properties --- .../MSFT_EXORecipientPermission.schema.mof | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof index 40d874461b..4a12e9bdce 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof @@ -1,8 +1,8 @@ [ClassVersion("1.0.0.0"), FriendlyName("EXORecipientPermission")] class MSFT_EXORecipientPermission : OMI_BaseResource { - [Write, Description("The mailbox the permission should be given on.")] String Identity; - [Write, Description("The account to give the permission to.")] String Trustee; + [Key, Description("The mailbox the permission should be given on.")] String Identity; + [Key, Description("The account to give the permission to.")] String Trustee; [Write, Description("The access rights granted to the account. Only 'SendAs' is supported.")] String AccessRights; [Write, Description("Present ensures the group exists, absent ensures it is removed"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; From d8e620ab8df155e606817aea48624fa5d2f4a9ef Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Fri, 5 Jan 2024 16:46:59 +0100 Subject: [PATCH 010/171] Fix nested change detection in CIMInstance --- .../Modules/M365DSCReport.psm1 | 260 +++++++++--------- 1 file changed, 132 insertions(+), 128 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index 7330466d83..97a8412f20 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -722,83 +722,85 @@ function Compare-M365DSCConfigurations { [string]$key = Get-M365DSCCimInstanceKey -CIMInstance $instance - if ($null -ne $key) - { - $destinationResourceInstances = $destinationResource.$destinationPropertyName | Where-Object -FilterScript {$_."$key" -eq $instance."$key"} + $destinationResourceInstances = $destinationResource.$destinationPropertyName | Where-Object -FilterScript {$_."$key" -eq $instance."$key"} - if ($null -ne $destinationResourceInstances) + if ($null -ne $destinationResourceInstances) + { + # There is a chance we found 2 instances of a CIMInstance based on its key property. + # If that's the case, loop through each instance found and if at least one of them is + # a perfect match, then don't consider this a drift. + $foundOneMatch = $false + $drift = $null + foreach ($destinationResourceInstance in $destinationResourceInstances) { - # There is a chance we found 2 instances of a CIMInstance based on its key property. - # If that's the case, loop through each instance found and if at least of of them is - # a perfect match, then don't consider this a drift. - $foundOneMatch = $false - $drift = $null - foreach ($destinationResourceInstance in $destinationResourceInstances) + $foundResourceMatch = $true + [array]$driftProperties = @() + foreach ($property in $instance.Keys) { - $foundResourceMatch = $true - foreach ($property in $instance.Keys) + if ($null -eq $destinationResourceInstance."$property" -or $null -ne (Compare-Object -ReferenceObject ($instance."$property")` + -DifferenceObject ($destinationResourceInstance."$property"))) { - if ($null -eq $destinationResourceInstance."$property" -or $null -ne (Compare-Object -ReferenceObject ($instance."$property")` - -DifferenceObject ($destinationResourceInstance."$property"))) - { - $drift = @{ - ResourceName = $sourceResource.ResourceName - ResourceInstanceName = $destinationResource.ResourceInstanceName - Key = $propertyName - KeyValue = $instance."$key" - Properties = @(@{ - ParameterName = $property - CIMInstanceKey = $key - CIMInstanceValue = $instance."$Key" - ValueInSource = $instance."$property" - ValueInDestination = $destinationResourceInstance."$property" - }) - } - $foundResourceMatch = $false + $driftProperties += @{ + ParameterName = $property + CIMInstanceKey = $key + CIMInstanceValue = $instance."$Key" + ValueInSource = $instance."$property" + ValueInDestination = $destinationResourceInstance."$property" } - } - if ($foundResourceMatch) - { - $foundOneMatch = $true + $foundResourceMatch = $false } } - if ($foundOneMatch) + if ($foundResourceMatch) { - # If a match was found, clear the drift. - $drift = $null + $foundOneMatch = $true } else { - $Delta += , $drift - $drift = $null + $drift = @{ + ResourceName = $sourceResource.ResourceName + ResourceInstanceName = $destinationResource.ResourceInstanceName + Key = $propertyName + KeyValue = $instance."$key" + Properties = $driftProperties + } } } + if ($foundOneMatch) + { + # If a match was found, clear the drift. + $drift = $null + } else { - # We have detected a drift where the CIM Instance exists in the Source but NOT in the Destination - $drift = @{ - ResourceName = $sourceResource.ResourceName - ResourceInstanceName = $destinationResource.ResourceInstanceName - Key = $propertyName - KeyValue = $instance."$key" - Properties = @(@{ - ParameterName = $propertyName - CIMInstanceKey = $key - CIMInstanceValue = $instance."$Key" - ValueInSource = $instance - ValueInDestination = $null - }) - } - if ($null -ne $drift) - { - $Delta += , $drift - $drift = $null - } + $Delta += , $drift + $drift = $null + } + } + else + { + # We have detected a drift where the CIM Instance exists in the Source but NOT in the Destination + $drift = @{ + ResourceName = $sourceResource.ResourceName + ResourceInstanceName = $destinationResource.ResourceInstanceName + Key = $propertyName + KeyValue = $instance."$key" + Properties = @(@{ + ParameterName = $propertyName + CIMInstanceKey = $key + CIMInstanceValue = $instance."$Key" + ValueInSource = $instance + ValueInDestination = $null + }) + } + if ($null -ne $drift) + { + $Delta += , $drift + $drift = $null } } } } - # Needs to be a separate nested if statement otherwise the ReferenceObject an be null and it will error out; + # Needs to be a separate nested if statement otherwise the ReferenceObject can be null and it will error out; elseif ($destinationResource.ContainsKey($destinationPropertyName) -eq $false -or (-not [System.String]::IsNullOrEmpty($propertyName) -and $null -ne (Compare-Object -ReferenceObject ($sourceResource.$propertyName)` -DifferenceObject ($destinationResource.$destinationPropertyName))) -and @@ -853,8 +855,8 @@ function Compare-M365DSCConfigurations } } - # Do the scan the other way around because there's a chance that the property, if null, wasn't part of the source - # object. By scanning against the destination we will catch properties that are not null on the source but not null in destination; + # Do the scan the other way around because there's a chance that the property, if null, wasn't part of the source object. + # By scanning against the destination we will catch properties that are not null on the source but not null in destination; foreach ($propertyName in $destinationResource.Keys) { if ($propertyName -notin $filteredProperties) @@ -871,89 +873,91 @@ function Compare-M365DSCConfigurations { [string]$key = Get-M365DSCCimInstanceKey -CIMInstance $instance - if ($null -ne $key) - { - $sourceResourceInstances = $sourceResource.$sourcePropertyName | Where-Object -FilterScript {$_."$key" -eq $instance."$key"} + $sourceResourceInstances = $sourceResource.$sourcePropertyName | Where-Object -FilterScript {$_."$key" -eq $instance."$key"} - if ($null -ne $sourceResourceInstances) + if ($null -ne $sourceResourceInstances) + { + # There is a chance we found 2 instances of a CIMInstance based on its key property. + # If that's the case, loop through each instance found and if at least one of them is + # a perfect match, then don't consider this a drift. + $foundOneMatch = $false + $drift = $null + foreach ($sourceResourceInstance in $sourceResourceInstances) { - # There is a chance we found 2 instances of a CIMInstance based on its key property. - # If that's the case, loop through each instance found and if at least of of them is - # a perfect match, then don't consider this a drift. - $foundOneMatch = $false - $drift = $null - foreach ($sourceResourceInstance in $sourceResourceInstances) + $innerDrift = $null + foreach ($property in $instance.Keys) { - foreach ($property in $instance.Keys) + if ($null -eq $sourceResourceInstance."$property" -or $null -ne (Compare-Object -ReferenceObject ($instance."$property")` + -DifferenceObject ($sourceResourceInstance."$property"))) { - if ($null -eq $sourceResourceInstance."$property" -or $null -ne (Compare-Object -ReferenceObject ($instance."$property")` - -DifferenceObject ($sourceResourceInstance."$property"))) + # Make sure we haven't already added this drift in the delta return object to prevent duplicates. + $existing = $delta | Where-Object -FilterScript {$_.ResourceName -eq $destinationResource.ResourceName -and ` + $_.ResourceInstanceName -eq $destinationResource.ResourceInstanceName} + + $sameEntry = $null + if ($null -ne $existing) { - # Make sure we haven't already added this drift in the delta return object to prevent duplicates. - $existing = $delta | Where-Object -FilterScript {$_.ResourceName -eq $destinationResource.ResourceName -and ` - $_.ResourceInstanceName -eq $destinationResource.ResourceInstanceName} - - $sameEntry = $null - if ($null -ne $existing) - { - $sameEntry = $existing.Properties | Where-Object -FilterScript {$_.ParameterName -eq $property -and ` - $_.CIMInstanceKey -eq $key -and ` - $_.CIMInstanceValue -eq ($instance."$key") -and ` - $_.ValueInSource -eq $sourceResourceInstance."$property" -and ` - $_.ValueInDestination -eq $instance."$property"} - } + $sameEntry = $existing.Properties | Where-Object -FilterScript {$_.ParameterName -eq $property -and ` + $_.CIMInstanceKey -eq $key -and ` + $_.CIMInstanceValue -eq ($instance."$key") -and ` + $_.ValueInSource -eq $sourceResourceInstance."$property" -and ` + $_.ValueInDestination -eq $instance."$property"} + } - if ($null -eq $sameEntry) - { - $drift = @{ - ResourceName = $destinationResource.ResourceName - ResourceInstanceName = $destinationResource.ResourceInstanceName - Key = $propertyName - KeyValue = $instance."$key" - Properties = @(@{ - ParameterName = $property - CIMInstanceKey = $key - CIMInstanceValue = $instance."$Key" - ValueInSource = $sourceResourceInstance."$property" - ValueInDestination = $instance."$property" - }) - } + if ($null -eq $sameEntry) + { + $innerDrift = @{ + ResourceName = $destinationResource.ResourceName + ResourceInstanceName = $destinationResource.ResourceInstanceName + Key = $propertyName + KeyValue = $instance."$key" + Properties = @(@{ + ParameterName = $property + CIMInstanceKey = $key + CIMInstanceValue = $instance."$Key" + ValueInSource = $sourceResourceInstance."$property" + ValueInDestination = $instance."$property" + }) } } } - if ($null -eq $drift) - { - $foundOneMatch = $true - } } - if ($foundOneMatch) + if ($null -eq $innerDrift) { - # If a match was found, clear the drift. - $drift = $null + $foundOneMatch = $true } - } - else - { - # We have detected a drift where the CIM Instance exists in the Destination but NOT in the Source - $drift = @{ - ResourceName = $destinationResource.ResourceName - ResourceInstanceName = $destinationResource.ResourceInstanceName - Key = $propertyName - KeyValue = $instance."$key" - Properties = @(@{ - ParameterName = $propertyName - CIMInstanceKey = $key - CIMInstanceValue = $instance."$Key" - ValueInSource = $null - ValueInDestination = $instance - }) - } - if ($null -ne $drift) + else { - $Delta += , $drift - $drift = $null + $drift = $innerDrift } } + if ($foundOneMatch) + { + # If a match was found, clear the drift. + $drift = $null + } + } + else + { + # We have detected a drift where the CIM Instance exists in the Destination but NOT in the Source + $drift = @{ + ResourceName = $destinationResource.ResourceName + ResourceInstanceName = $destinationResource.ResourceInstanceName + Key = $propertyName + KeyValue = $instance."$key" + Properties = @(@{ + ParameterName = $propertyName + CIMInstanceKey = $key + CIMInstanceValue = $instance."$Key" + ValueInSource = $null + ValueInDestination = $instance + }) + } + if ($null -ne $drift) + { + $Delta += , $drift + $drift = $null + } } } } From 71295a4c6993e21d060d2ab105920fc77b73a816 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Fri, 5 Jan 2024 16:47:54 +0100 Subject: [PATCH 011/171] Fix enrollment platform restriction comparison during report creation --- CHANGELOG.md | 6 ++++++ Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80c14b376f..e461866fec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* M365DSCReport + * Fix nested change detection for CIMInstances + * Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report + # 1.24.110.1 * AADAdministrativeUnit diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index 97a8412f20..3fabb2eff1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -1155,6 +1155,10 @@ function Get-M365DSCResourceKey { return @('Id') } + if ($Resource.ResourceName -eq 'IntuneDeviceEnrollmentPlatformRestriction' -and $Resource.Keys.Where({ $_ -like "*Restriction"})) + { + return @('ResourceInstanceName') + } if ($Resource.ResourceName -eq 'TeamsChannel' -and -not [System.String]::IsNullOrEmpty($Resource.TeamName)) { # Teams Channel displaynames are not tenant-unique (e.g. "General" is almost in every team), but should be unique per team From 64ba4e76086676ed20d03910207e8998913011a9 Mon Sep 17 00:00:00 2001 From: Vasily Date: Mon, 15 Jan 2024 17:52:08 +0100 Subject: [PATCH 012/171] Update MSFT_AADGroup.psm1 line 1050 changed from if ($Filter -like "*endsWith*") to if ($Filter -like "*endsWith*" -or $Filter -like "*onPremisesSyncEnabled eq null*" -or $Filter -like "*onPremisesSyncEnabled ne true*") it resolves the issue in #3935 --- .../DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index 293ac6fd29..b29de29524 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1047,7 +1047,7 @@ function Export-TargetResource All = [switch]$true ErrorAction = 'Stop' } - if ($Filter -like "*endsWith*") { + if ($Filter -like "*endsWith*" -or $Filter -like "*onPremisesSyncEnabled eq null*" -or $Filter -like "*onPremisesSyncEnabled ne true*") { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } From 41b2de219af8a769014c9096f8e08d3983fe21a3 Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 16 Jan 2024 11:50:16 +0100 Subject: [PATCH 013/171] Update MSFT_AADGroup.psm1 line 1050 changed from if ($Filter -like "endsWith") to if ($Filter -like "endsWith" -or $Filter -like "onPremisesSyncEnabled eq null") removing "onPremisesSyncEnabled ne true" per https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http#group-properties This Pull Request (PR) fixes the following issues it resolves the issue in #3935 --- .../DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index b29de29524..a38c38f8f2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1047,7 +1047,7 @@ function Export-TargetResource All = [switch]$true ErrorAction = 'Stop' } - if ($Filter -like "*endsWith*" -or $Filter -like "*onPremisesSyncEnabled eq null*" -or $Filter -like "*onPremisesSyncEnabled ne true*") { + if ($Filter -like "*endsWith*" -or $Filter -like "*onPremisesSyncEnabled eq null*") { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } From d1232d9de6a4d780d4bb9564e9c1e6d09e3e9a07 Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 16 Jan 2024 14:58:14 +0100 Subject: [PATCH 014/171] Update MSFT_AADGroup.psm1 added the block to check allowed advanced Group properties from the table https://learn.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http#group-properties that support eq null. --- .../MSFT_AADGroup/MSFT_AADGroup.psm1 | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index a38c38f8f2..f9d6d4232c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1047,10 +1047,36 @@ function Export-TargetResource All = [switch]$true ErrorAction = 'Stop' } - if ($Filter -like "*endsWith*" -or $Filter -like "*onPremisesSyncEnabled eq null*") { + + # Define the list of attributes + $attributesToCheck = @( + "description", + "displayName", + "hasMembersWithLicenseErrors", + "mail", + "mailNickname", + "onPremisesSecurityIdentifier", + "onPremisesSyncEnabled", + "preferredLanguage" + ) + + # Initialize a flag to indicate whether any attribute matches the condition + $matchConditionFound = $false + + # Check each attribute in the list + foreach ($attribute in $attributesToCheck) { + if ($Filter -like "*$attribute eq null*") { + $matchConditionFound = $true + break + } + } + + # If any attribute matches, add parameters to $ExportParameters + if ($matchConditionFound) { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } + [array] $Script:exportedGroups = Get-MgGroup @ExportParameters $Script:exportedGroups = $Script:exportedGroups | Where-Object -FilterScript { -not ($_.MailEnabled -and ($null -eq $_.GroupTypes -or $_.GroupTypes.Length -eq 0)) -and ` From ab9714b7d887e17ed7d1db8e19b927e3fe97378e Mon Sep 17 00:00:00 2001 From: Vasily Date: Tue, 16 Jan 2024 15:07:04 +0100 Subject: [PATCH 015/171] Update MSFT_AADGroup.psm1 added "endWIth" into condition to switch to advanced query if ($matchConditionFound -or $Filter -like "*endsWith*")) { --- .../DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index f9d6d4232c..1e9eacab06 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1072,7 +1072,7 @@ function Export-TargetResource } # If any attribute matches, add parameters to $ExportParameters - if ($matchConditionFound) { + if ($matchConditionFound -or $Filter -like "*endsWith*")) { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } From 74d0367c656f96fcaacf090846ba9cb80c528a8b Mon Sep 17 00:00:00 2001 From: Philippe Kernevez Date: Fri, 19 Jan 2024 12:15:31 +0100 Subject: [PATCH 016/171] Move limit from 100 to 1000 with a log message if max is reach --- CHANGELOG.md | 3 +++ .../MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 | 7 ++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78bafaa588..530326f417 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ * Removed the ability to specify a value of Absent for the Ensure property. * AADCrossTenantAccessPolicyCOnfigurationDefault * Removed the ability to specify a value of Absent for the Ensure property. +* TeamsCallQueue + * Optimize performances by doing 1 request instead of n+1 + FIXES [[#4192](https://github.com/microsoft/Microsoft365DSC/issues/4192)] # 1.24.117.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 index 6c3f10b87a..f9b4b9d430 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 @@ -892,7 +892,12 @@ function Export-TargetResource { $i = 1 $Script:ExportMode = $true - [array] $Script:exportedInstances = Get-CsCallQueue -ErrorAction Stop + $Script:MaxSize = 1000 + [array] $Script:exportedInstances = Get-CsCallQueue -ErrorAction Stop -First $Script:MaxSize + if ($Script:exportedInstances.Count -eq $Script:MaxSize){ + Write-Verbose -Message "WARNING: CsCallQueue isn't exporting all of them, you reach the max size." + } + $dscContent = [System.Text.StringBuilder]::New() Write-Host "`r`n" -NoNewline foreach ($instance in $exportedInstances) From aa69bc488a3f83469a312aeddb53fc41bd02c582 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Fri, 26 Jan 2024 01:47:08 +0000 Subject: [PATCH 017/171] Fix condition when resource is absent --- CHANGELOG.md | 20 +++++++++++++++++-- ...urationPolicyAndroidOpenSourceProject.psm1 | 2 +- ...otectionPolicyWindows10SettingCatalog.psm1 | 2 +- .../MSFT_IntuneRoleAssignment.psm1 | 2 +- .../MSFT_IntuneRoleDefinition.psm1 | 2 +- ...SettingCatalogASRRulesPolicyWindows10.psm1 | 2 +- ...ationPolicyAndroidDeviceAdministrator.psm1 | 2 +- ...ionPolicyAndroidEnterpriseDeviceOwner.psm1 | 2 +- ...ionPolicyAndroidEnterpriseWorkProfile.psm1 | 2 +- ...WifiConfigurationPolicyAndroidForWork.psm1 | 2 +- ...urationPolicyAndroidOpenSourceProject.psm1 | 2 +- ...MSFT_IntuneWifiConfigurationPolicyIOS.psm1 | 2 +- ...FT_IntuneWifiConfigurationPolicyMacOS.psm1 | 2 +- ...ntuneWifiConfigurationPolicyWindows10.psm1 | 2 +- .../MSFT_TeamsCallParkPolicy.psm1 | 2 +- 15 files changed, 32 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531a56fd91..5e2eae0a07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneDeviceConfigurationPolicyAndroidOpenSourceProject, + IntuneExploitProtectionPolicyWindows10SettingCatalog, IntuneRoleAssignment, + IntuneRoleDefinition, IntuneSettingCatalogASRRulesPolicyWindows10, + IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator, + IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner, + IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile, + IntuneWifiConfigurationPolicyAndroidForWork, + IntuneWifiConfigurationPolicyAndroidOpenSourceProject, + IntuneWifiConfigurationPolicyIOS, IntuneWifiConfigurationPolicyMacOS, + IntuneWifiConfigurationPolicyWindows10, TeamsCallParkPolicy + * Fix condition in Test-TargetResource when resource is absent + FIXES [#3897](https://github.com/microsoft/Microsoft365DSC/issues/3897) + FIXES [#4256](https://github.com/microsoft/Microsoft365DSC/issues/4256) + # 1.24.124.1 * AADAuthenticationMethodPolicyAuthenticator @@ -20,7 +36,7 @@ * Remove the logic path to create a new instance in favor of the update flow. * AADConditionalAccessPolicy * Fix issue when not all parameters are specified - FIXES [[#4202](https://github.com/microsoft/Microsoft365DSC/issues/4202)] + FIXES [#4202](https://github.com/microsoft/Microsoft365DSC/issues/4202) * AADCrossTenantAccessPolicy * Removed the ability to specify a value of Absent for the Ensure property. * AADCrossTenantAccessPolicyCOnfigurationDefault @@ -39,7 +55,7 @@ * DEPRECATED Resource. * SCAutoSensitivityLabelRule * Correct export indentation, which caused an issue with report conversion to JSON. - FIXES [[#4240](https://github.com/microsoft/Microsoft365DSC/issues/4240)] + FIXES [#4240](https://github.com/microsoft/Microsoft365DSC/issues/4240) * SPOSharingSettings * Fixed an Issue where the MySiteSharingCapability could be returned as an empty string instead of a null value from the Get method. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject.psm1 index d98004d87a..72f8b9ab6e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneDeviceConfigurationPolicyAndroidOpenSourceProject.psm1 @@ -589,7 +589,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog.psm1 index 8811c5d473..45cfe819b4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog/MSFT_IntuneExploitProtectionPolicyWindows10SettingCatalog.psm1 @@ -430,7 +430,7 @@ function Test-TargetResource $ValuesToCheck.Remove('ApplicationSecret') | Out-Null $ValuesToCheck.Remove('Identity') | Out-Null - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message 'The policy was not found' return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleAssignment/MSFT_IntuneRoleAssignment.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleAssignment/MSFT_IntuneRoleAssignment.psm1 index 058a2e58d7..5cd954e832 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleAssignment/MSFT_IntuneRoleAssignment.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleAssignment/MSFT_IntuneRoleAssignment.psm1 @@ -559,7 +559,7 @@ function Test-TargetResource } $PSBoundParameters.Set_Item('ResourceScopes', $ResourceScopes) - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleDefinition/MSFT_IntuneRoleDefinition.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleDefinition/MSFT_IntuneRoleDefinition.psm1 index 2c0ee65b94..51e23548ee 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleDefinition/MSFT_IntuneRoleDefinition.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneRoleDefinition/MSFT_IntuneRoleDefinition.psm1 @@ -403,7 +403,7 @@ function Test-TargetResource $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index 5fff32e897..1544d5a942 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -716,7 +716,7 @@ function Test-TargetResource $ValuesToCheck.Remove('TenantId') | Out-Null $ValuesToCheck.Remove('ApplicationSecret') | Out-Null - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message 'The policy was not found' return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator.psm1 index 550848afb0..063e280aa2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator/MSFT_IntuneWiFiConfigurationPolicyAndroidDeviceAdministrator.psm1 @@ -474,7 +474,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner.psm1 index e76afffc7c..18122fecbc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseDeviceOwner.psm1 @@ -565,7 +565,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile.psm1 index a053896d55..1c43c44ddd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile/MSFT_IntuneWifiConfigurationPolicyAndroidEnterpriseWorkProfile.psm1 @@ -472,7 +472,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidForWork/MSFT_IntuneWifiConfigurationPolicyAndroidForWork.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidForWork/MSFT_IntuneWifiConfigurationPolicyAndroidForWork.psm1 index 65f8ed0088..f662b18c5e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidForWork/MSFT_IntuneWifiConfigurationPolicyAndroidForWork.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidForWork/MSFT_IntuneWifiConfigurationPolicyAndroidForWork.psm1 @@ -471,7 +471,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject.psm1 index 70ed28d0bf..35f605ec13 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject/MSFT_IntuneWifiConfigurationPolicyAndroidOpenSourceProject.psm1 @@ -497,7 +497,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyIOS/MSFT_IntuneWifiConfigurationPolicyIOS.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyIOS/MSFT_IntuneWifiConfigurationPolicyIOS.psm1 index e710718398..fa1376d8fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyIOS/MSFT_IntuneWifiConfigurationPolicyIOS.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyIOS/MSFT_IntuneWifiConfigurationPolicyIOS.psm1 @@ -551,7 +551,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyMacOS/MSFT_IntuneWifiConfigurationPolicyMacOS.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyMacOS/MSFT_IntuneWifiConfigurationPolicyMacOS.psm1 index d1bf3f164c..fa8ad74a13 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyMacOS/MSFT_IntuneWifiConfigurationPolicyMacOS.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyMacOS/MSFT_IntuneWifiConfigurationPolicyMacOS.psm1 @@ -538,7 +538,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyWindows10/MSFT_IntuneWifiConfigurationPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyWindows10/MSFT_IntuneWifiConfigurationPolicyWindows10.psm1 index 62701eca3b..2dc45c9668 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyWindows10/MSFT_IntuneWifiConfigurationPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWifiConfigurationPolicyWindows10/MSFT_IntuneWifiConfigurationPolicyWindows10.psm1 @@ -581,7 +581,7 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 index aaba733498..5f6cbc06d0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 @@ -295,7 +295,7 @@ function Test-TargetResource $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() $ValuesToCheck.Remove('Identity') | Out-Null - if ($CurrentValues.Ensure -eq 'Absent') + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false From 92a6e411c9b94d969087122a4037ed791a11fe3e Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Fri, 26 Jan 2024 01:49:50 +0000 Subject: [PATCH 018/171] Add default value to parameter Ensure --- CHANGELOG.md | 2 ++ .../MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e2eae0a07..f5ed6f43d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ * Fix condition in Test-TargetResource when resource is absent FIXES [#3897](https://github.com/microsoft/Microsoft365DSC/issues/3897) FIXES [#4256](https://github.com/microsoft/Microsoft365DSC/issues/4256) +* TeamsFilesPolicy + * Add default value ('Present') to parameter Ensure # 1.24.124.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 index 62af2c60f4..36b91fb1a5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 @@ -21,7 +21,7 @@ function Get-TargetResource [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] - $Ensure, + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -112,7 +112,7 @@ function Set-TargetResource [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] - $Ensure, + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] @@ -225,7 +225,7 @@ function Test-TargetResource [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] - $Ensure, + $Ensure = 'Present', [Parameter()] [System.Management.Automation.PSCredential] From d23fae0fbe5ba5986ec5b21c715d4ac85fd22896 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 26 Jan 2024 07:07:51 -0500 Subject: [PATCH 019/171] Added Support for Managed Identity in Teams --- CHANGELOG.md | 7 +++ .../MSFT_TeamsAppPermissionPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsAppPermissionPolicy.schema.mof | 1 + .../MSFT_TeamsAppSetupPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsAppSetupPolicy.schema.mof | 1 + .../MSFT_TeamsAudioConferencingPolicy.psm1 | 21 +++++++-- ...FT_TeamsAudioConferencingPolicy.schema.mof | 1 + .../MSFT_TeamsCallHoldPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsCallHoldPolicy.schema.mof | 1 + .../MSFT_TeamsCallParkPolicy.psm1 | 23 +++++++-- .../MSFT_TeamsCallParkPolicy.schema.mof | 1 + .../MSFT_TeamsCallQueue.psm1 | 27 +++++++++-- .../MSFT_TeamsCallQueue.schema.mof | 1 + .../MSFT_TeamsCallingPolicy.psm1 | 28 +++++++++-- .../MSFT_TeamsCallingPolicy.schema.mof | 1 + .../MSFT_TeamsChannel/MSFT_TeamsChannel.psm1 | 27 +++++++++-- .../MSFT_TeamsChannel.schema.mof | 2 +- .../MSFT_TeamsChannelTab.psm1 | 30 +++++++++--- .../MSFT_TeamsChannelTab.schema.mof | 2 +- .../MSFT_TeamsChannelsPolicy.psm1 | 27 +++++++++-- .../MSFT_TeamsChannelsPolicy.schema.mof | 1 + .../MSFT_TeamsClientConfiguration.psm1 | 27 +++++++++-- .../MSFT_TeamsClientConfiguration.schema.mof | 2 +- .../MSFT_TeamsComplianceRecordingPolicy.psm1 | 21 +++++++-- ..._TeamsComplianceRecordingPolicy.schema.mof | 1 + .../MSFT_TeamsCortanaPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsCortanaPolicy.schema.mof | 1 + ...TeamsDialInConferencingTenantSettings.psm1 | 27 +++++++++-- ...ialInConferencingTenantSettings.schema.mof | 1 + .../MSFT_TeamsEmergencyCallRoutingPolicy.psm1 | 27 +++++++++-- ...TeamsEmergencyCallRoutingPolicy.schema.mof | 1 + .../MSFT_TeamsEmergencyCallingPolicy.psm1 | 27 +++++++++-- ...SFT_TeamsEmergencyCallingPolicy.schema.mof | 1 + .../MSFT_TeamsEnhancedEncryptionPolicy.psm1 | 21 +++++++-- ...T_TeamsEnhancedEncryptionPolicy.schema.mof | 1 + .../MSFT_TeamsEventsPolicy.psm1 | 27 +++++++++-- .../MSFT_TeamsEventsPolicy.schema.mof | 1 + .../MSFT_TeamsFederationConfiguration.psm1 | 27 +++++++++-- ...FT_TeamsFederationConfiguration.schema.mof | 1 + .../MSFT_TeamsFeedbackPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsFeedbackPolicy.schema.mof | 1 + .../MSFT_TeamsFilesPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsFilesPolicy.schema.mof | 1 + .../MSFT_TeamsGroupPolicyAssignment.psm1 | 26 +++++++++-- ...MSFT_TeamsGroupPolicyAssignment.schema.mof | 2 +- .../MSFT_TeamsGuestCallingConfiguration.psm1 | 27 +++++++++-- ..._TeamsGuestCallingConfiguration.schema.mof | 2 +- .../MSFT_TeamsGuestMeetingConfiguration.psm1 | 27 +++++++++-- ..._TeamsGuestMeetingConfiguration.schema.mof | 1 + ...MSFT_TeamsGuestMessagingConfiguration.psm1 | 27 +++++++++-- ...eamsGuestMessagingConfiguration.schema.mof | 2 +- .../MSFT_TeamsIPPhonePolicy.psm1 | 21 +++++++-- .../MSFT_TeamsIPPhonePolicy.schema.mof | 1 + ...FT_TeamsMeetingBroadcastConfiguration.psm1 | 27 +++++++++-- ...msMeetingBroadcastConfiguration.schema.mof | 2 +- .../MSFT_TeamsMeetingBroadcastPolicy.psm1 | 27 +++++++++-- ...SFT_TeamsMeetingBroadcastPolicy.schema.mof | 2 +- .../MSFT_TeamsMeetingConfiguration.psm1 | 27 +++++++++-- .../MSFT_TeamsMeetingConfiguration.schema.mof | 2 +- .../MSFT_TeamsMeetingPolicy.schema.mof | Bin 30946 -> 31138 bytes .../MSFT_TeamsMessagingPolicy.psm1 | 27 +++++++++-- .../MSFT_TeamsMessagingPolicy.schema.mof | 2 +- .../MSFT_TeamsMobilityPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsMobilityPolicy.schema.mof | 1 + .../MSFT_TeamsNetworkRoamingPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsNetworkRoamingPolicy.schema.mof | 1 + .../MSFT_TeamsOnlineVoiceUser.psm1 | 26 +++++++++-- .../MSFT_TeamsOnlineVoiceUser.schema.mof | Bin 2760 -> 2952 bytes .../MSFT_TeamsOnlineVoicemailPolicy.psm1 | 27 +++++++++-- ...MSFT_TeamsOnlineVoicemailPolicy.schema.mof | Bin 5160 -> 5352 bytes ...MSFT_TeamsOnlineVoicemailUserSettings.psm1 | 29 ++++++++++-- ...eamsOnlineVoicemailUserSettings.schema.mof | 1 + .../MSFT_TeamsOrgWideAppSettings.schema.mof | 2 +- .../MSFT_TeamsPstnUsage.psm1 | 27 +++++++++-- .../MSFT_TeamsPstnUsage.schema.mof | 1 + .../MSFT_TeamsShiftsPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsShiftsPolicy.schema.mof | 1 + .../MSFT_TeamsTeam/MSFT_TeamsTeam.psm1 | 27 +++++++++-- .../MSFT_TeamsTeam/MSFT_TeamsTeam.schema.mof | 2 +- .../MSFT_TeamsTemplatesPolicy.psm1 | 28 +++++++++-- .../MSFT_TeamsTemplatesPolicy.schema.mof | 2 +- .../MSFT_TeamsTenantDialPlan.psm1 | 44 +++++++++++++----- .../MSFT_TeamsTenantDialPlan.schema.mof | 2 +- .../MSFT_TeamsTenantNetworkRegion.psm1 | 21 +++++++-- .../MSFT_TeamsTenantNetworkRegion.schema.mof | 1 + .../MSFT_TeamsTenantNetworkSite.psm1 | 25 ++++++++-- .../MSFT_TeamsTenantNetworkSite.schema.mof | 1 + .../MSFT_TeamsTenantNetworkSubnet.psm1 | 20 ++++++-- .../MSFT_TeamsTenantNetworkSubnet.schema.mof | 1 + .../MSFT_TeamsTenantTrustedIPAddress.psm1 | 21 +++++++-- ...SFT_TeamsTenantTrustedIPAddress.schema.mof | 1 + .../MSFT_TeamsTranslationRule.psm1 | 21 +++++++-- .../MSFT_TeamsTranslationRule.schema.mof | 1 + .../MSFT_TeamsUnassignedNumberTreatment.psm1 | 21 +++++++-- ..._TeamsUnassignedNumberTreatment.schema.mof | 1 + .../MSFT_TeamsUpdateManagementPolicy.psm1 | 22 +++++++-- ...SFT_TeamsUpdateManagementPolicy.schema.mof | 1 + .../MSFT_TeamsUpgradeConfiguration.psm1 | 27 +++++++++-- .../MSFT_TeamsUpgradeConfiguration.schema.mof | 2 +- .../MSFT_TeamsUpgradePolicy.psm1 | 26 +++++++++-- .../MSFT_TeamsUpgradePolicy.schema.mof | 2 +- .../MSFT_TeamsUser/MSFT_TeamsUser.psm1 | 27 +++++++++-- .../MSFT_TeamsUser/MSFT_TeamsUser.schema.mof | 2 +- .../MSFT_TeamsUserCallingSettings.schema.mof | 1 + .../MSFT_TeamsUserPolicyAssignment.psm1 | 26 +++++++++-- .../MSFT_TeamsUserPolicyAssignment.schema.mof | 2 +- .../MSFT_TeamsVdiPolicy.psm1 | 21 +++++++-- .../MSFT_TeamsVdiPolicy.schema.mof | 1 + .../MSFT_TeamsVoiceRoute.psm1 | 28 +++++++++-- .../MSFT_TeamsVoiceRoute.schema.mof | 2 +- .../MSFT_TeamsVoiceRoutingPolicy.psm1 | 27 +++++++++-- .../MSFT_TeamsVoiceRoutingPolicy.schema.mof | 2 +- .../MSFT_TeamsWorkloadPolicy.psm1 | 25 ++++++++-- .../MSFT_TeamsWorkloadPolicy.schema.mof | 1 + .../Dependencies/Manifest.psd1 | 2 +- .../authentication-and-permissions.md | 2 +- 116 files changed, 1209 insertions(+), 255 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531a56fd91..082dccf9c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* TEAMS + * Added support for ManagedIdentity Authentication across Teams resources. +* DEPENDENCIES + * Updated MSCloudLoginAssistant dependencies to version 1.1.9. + # 1.24.124.1 * AADAuthenticationMethodPolicyAuthenticator diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.psm1 index 2b1116f93a..2d827e4c6b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.psm1 @@ -55,7 +55,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -116,6 +120,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -187,7 +192,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -327,7 +336,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -441,7 +454,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.schema.mof index 14e44cfc7a..ca2196ca1b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppPermissionPolicy/MSFT_TeamsAppPermissionPolicy.schema.mof @@ -14,4 +14,5 @@ class MSFT_TeamsAppPermissionPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.psm1 index 7d4a44b0b7..6e99c8ba52 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.psm1 @@ -55,7 +55,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -98,6 +102,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -169,7 +174,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -327,7 +336,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -437,7 +450,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.schema.mof index 0360966308..a3b04dd714 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAppSetupPolicy/MSFT_TeamsAppSetupPolicy.schema.mof @@ -14,4 +14,5 @@ class MSFT_TeamsAppSetupPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.psm1 index 28dd0906ff..43a53564cd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.psm1 @@ -35,7 +35,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -73,6 +77,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -124,7 +129,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -235,7 +244,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -360,7 +373,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.schema.mof index b589cf0147..869ee0e48d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsAudioConferencingPolicy/MSFT_TeamsAudioConferencingPolicy.schema.mof @@ -9,4 +9,5 @@ class MSFT_TeamsAudioConferencingPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.psm1 index 8a4ccd202d..1df4ef83b1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.psm1 @@ -35,7 +35,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -73,6 +77,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -124,7 +129,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -235,7 +244,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -360,7 +373,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.schema.mof index a39de434c6..8777ca8288 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallHoldPolicy/MSFT_TeamsCallHoldPolicy.schema.mof @@ -9,4 +9,5 @@ class MSFT_TeamsCallHoldPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 index aaba733498..1106286ec6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.psm1 @@ -47,7 +47,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -88,6 +92,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -151,7 +156,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -274,7 +283,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -293,8 +306,8 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() - $ValuesToCheck.Remove('Identity') | Out-Null + $ValuesToCheck.Remove('Identity') | Out-Null if ($CurrentValues.Ensure -eq 'Absent') { Write-Verbose -Message "Test-TargetResource returned $false" @@ -399,7 +412,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.schema.mof index 40b026991c..b76bf0c497 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallParkPolicy/MSFT_TeamsCallParkPolicy.schema.mof @@ -12,4 +12,5 @@ class MSFT_TeamsCallParkPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 index 6c3f10b87a..d3f8b19d33 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.psm1 @@ -221,7 +221,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting configuration of Teams Call Queue {$Name}" @@ -308,6 +312,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } } @@ -545,7 +550,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting configuration of Teams Call Queue {$Name}" @@ -573,6 +582,7 @@ function Set-TargetResource $opsParameters.Remove('TenantId') | Out-Null $opsParameters.Remove('CertificateThumbprint') | Out-Null $opsParameters.Remove('Ensure') | Out-Null + $opsParameters.Remove('ManagedIdentity') | Out-Null if ($currentValues.Ensure -eq 'Absent' -and 'Present' -eq $Ensure ) { @@ -817,7 +827,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -871,7 +885,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -906,6 +924,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.schema.mof index dc9d7419c7..f3e4c87d94 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallQueue/MSFT_TeamsCallQueue.schema.mof @@ -54,5 +54,6 @@ class MSFT_TeamsCallQueue : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.psm1 index f0daee685f..ff3d791bea 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.psm1 @@ -115,7 +115,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Calling Policy $($Identity)" @@ -175,6 +179,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -305,7 +310,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting Teams Calling Policy' @@ -333,6 +342,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null if ($Ensure -eq 'Present' -and $CurrentValues.Ensure -eq 'Absent') { @@ -470,7 +480,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -492,7 +506,6 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Credential') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` @@ -524,7 +537,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -557,6 +574,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.schema.mof index 993a8461ac..3dbbd080f0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCallingPolicy/MSFT_TeamsCallingPolicy.schema.mof @@ -27,5 +27,6 @@ class MSFT_TeamsCallingPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.psm1 index 99cd1302ee..5a447d7540 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.psm1 @@ -46,7 +46,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting configuration of Teams channel $DisplayName" @@ -117,6 +121,7 @@ function Get-TargetResource TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint Credential = $Credential + ManagedIdentity = $ManagedIdentity.IsPresent } if ($NewDisplayName) @@ -184,7 +189,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting configuration of Teams channel $DisplayName" @@ -219,6 +228,7 @@ function Set-TargetResource $CurrentParameters.Remove('TenantId') | Out-Null $CurrentParameters.Remove('CertificateThumbprint') | Out-Null $CurrentParameters.Remove('Ensure') | Out-Null + $CurrentParameters.Remove('ManagedIdentity') | Out-Null if ($CurrentParameters.ContainsKey('GroupId')) { $CurrentParameters.GroupId = $team.GroupId @@ -309,7 +319,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -360,7 +374,11 @@ function Export-TargetResource [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -401,6 +419,7 @@ function Export-TargetResource TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint Credential = $Credential + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.schema.mof index 123dde5109..e66d644319 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannel/MSFT_TeamsChannel.schema.mof @@ -11,5 +11,5 @@ class MSFT_TeamsChannel : OMI_BaseResource [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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.psm1 index 34fc8b7715..eaf6a683f7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.psm1 @@ -66,7 +66,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting configuration of Tab $DisplayName" @@ -184,6 +188,7 @@ function Get-TargetResource TenantId = $TenantID CertificateThumbprint = $CertificateThumbprint Ensure = 'Present' + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -265,7 +270,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting configuration of Team $DisplayName" @@ -293,6 +302,7 @@ function Set-TargetResource $CurrentParameters.Remove('TenantId') | Out-Null $CurrentParameters.Remove('CertificateThumbprint') | Out-Null $CurrentParameters.Remove('Credential') | Out-Null + $CurrentParameters.Remove('ManagedIdentity') | Out-Null Write-Verbose -Message "Retrieving Team Channel {$ChannelName} from Team {$($tab.TeamId)}" $ChannelInstance = Get-MgBetaTeamChannel -TeamId $tab.TeamId ` @@ -438,7 +448,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -461,9 +475,6 @@ function Test-TargetResource Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('CertificateThumbprint') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` @@ -495,7 +506,11 @@ function Export-TargetResource [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` @@ -570,6 +585,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.schema.mof index 75da7fcdb1..62c2b473b9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelTab/MSFT_TeamsChannelTab.schema.mof @@ -16,5 +16,5 @@ class MSFT_TeamsChannelTab : OMI_BaseResource [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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.psm1 index 1f7f9c4404..e78cd1c8ed 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.psm1 @@ -55,7 +55,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Channels Policy $($Identity)" @@ -103,6 +107,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -173,7 +178,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting Teams Channel Policy' @@ -201,6 +210,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null if ($Ensure -eq 'Present' -and $CurrentValues.Ensure -eq 'Absent') { @@ -278,7 +288,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -331,7 +345,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -363,6 +381,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.schema.mof index 89c46ea0f6..a2584258cc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsChannelsPolicy/MSFT_TeamsChannelsPolicy.schema.mof @@ -14,4 +14,5 @@ class MSFT_TeamsChannelsPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 index 000e689dd9..92e120994d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.psm1 @@ -81,7 +81,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Client' @@ -129,6 +133,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } if ([System.String]::IsNullOrEmpty($RestrictedSenderList)) { @@ -230,7 +235,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Client' @@ -255,6 +264,7 @@ function Set-TargetResource $SetParams.Remove('ApplicationId') | Out-Null $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null if ([System.String]::IsNullOrEmpty($RestrictedSenderList)) { @@ -356,7 +366,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -413,7 +427,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -440,6 +458,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.schema.mof index 47a8ebd921..f736444075 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsClientConfiguration/MSFT_TeamsClientConfiguration.schema.mof @@ -20,5 +20,5 @@ class MSFT_TeamsClientConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 index 4a37550baa..3cd4f041a4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.psm1 @@ -47,7 +47,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -97,6 +101,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -160,7 +165,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -283,7 +292,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -408,7 +421,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof index 25f29236af..0f32b2c355 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsComplianceRecordingPolicy/MSFT_TeamsComplianceRecordingPolicy.schema.mof @@ -12,4 +12,5 @@ class MSFT_TeamsComplianceRecordingPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.psm1 index 6e61b8db5e..9000814b1a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.psm1 @@ -36,7 +36,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -74,6 +78,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -126,7 +131,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -238,7 +247,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -363,7 +376,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.schema.mof index 09ce6cdd0c..21f463f839 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsCortanaPolicy/MSFT_TeamsCortanaPolicy.schema.mof @@ -9,4 +9,5 @@ class MSFT_TeamsCortanaPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.psm1 index bb9a77e5ff..b088d9fa4e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.psm1 @@ -60,7 +60,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting the Teams Dial In Conferencing Tenant Settings' @@ -103,6 +107,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -178,7 +183,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting Teams Dial In Conferencing Tenant Settings' @@ -206,6 +215,7 @@ function Set-TargetResource $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null $SetParameters.Remove('IsSingleInstance') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null try { @@ -283,7 +293,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -336,7 +350,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -362,6 +380,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.schema.mof index c8f30fb43f..1cfaa128bd 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsDialInConferencingTenantSettings/MSFT_TeamsDialInConferencingTenantSettings.schema.mof @@ -15,4 +15,5 @@ class MSFT_TeamsDialInConferencingTenantSettings : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 index 76e12f46e1..2a1b6e6e76 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 @@ -39,7 +39,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Emergency Call Routing Policy $Identity" @@ -82,6 +86,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } if ($policy.EmergencyNumbers.Count -gt 0) @@ -143,7 +148,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting Teams Emergency Call Routing Policy {$Identity}" @@ -188,6 +197,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null if ($PSBoundParameters.ContainsKey('EmergencyNumbers')) { @@ -275,7 +285,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -335,7 +349,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -367,6 +385,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $result = Get-TargetResource @params $result = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.schema.mof index 0c044f01ed..0a7d6ed6da 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.schema.mof @@ -17,4 +17,5 @@ class MSFT_TeamsEmergencyCallRoutingPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.psm1 index b047caaebe..b93c36c008 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.psm1 @@ -54,7 +54,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Emergency Calling Policy {$Identity}" @@ -100,6 +104,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } if ([System.String]::IsNullOrEmpty($result.NotificationMode)) @@ -176,7 +181,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting Teams Emergency Calling Policy {$Identity}" @@ -221,6 +230,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null if ($Ensure -eq 'Present' -and $CurrentValues.Ensure -eq 'Absent') { @@ -297,7 +307,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -350,7 +364,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -388,6 +406,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.schema.mof index 1d5650973f..5b2bdb9364 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallingPolicy/MSFT_TeamsEmergencyCallingPolicy.schema.mof @@ -13,4 +13,5 @@ class MSFT_TeamsEmergencyCallingPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.psm1 index 48da559d9d..2fc0ef8df9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.psm1 @@ -39,7 +39,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -78,6 +82,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -133,7 +138,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -248,7 +257,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -373,7 +386,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.schema.mof index 59e3fd96d5..525e169db9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEnhancedEncryptionPolicy/MSFT_TeamsEnhancedEncryptionPolicy.schema.mof @@ -10,4 +10,5 @@ class MSFT_TeamsEnhancedEncryptionPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.psm1 index 8ccbb925c6..c1b05c7b9c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.psm1 @@ -79,7 +79,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Events Policy {$Identity}" @@ -130,6 +134,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return $result @@ -226,7 +231,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting Teams Events Policy {$Identity}" @@ -254,6 +263,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null if ($Ensure -eq 'Present' -and $CurrentValues.Ensure -eq 'Absent') { @@ -353,7 +363,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -407,7 +421,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -445,6 +463,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.schema.mof index f8d8aea02d..b1c20537d6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEventsPolicy/MSFT_TeamsEventsPolicy.schema.mof @@ -18,4 +18,5 @@ class MSFT_TeamsEventsPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.psm1 index 6fe1ae47e6..47d7c7bf01 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.psm1 @@ -59,7 +59,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Federation' @@ -124,6 +128,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -198,7 +203,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Federation' @@ -224,6 +233,7 @@ function Set-TargetResource $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null $SetParams.Remove('AllowedDomains') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null if ($allowedDomains.Length -gt 0) { $SetParams.Add('AllowedDomainsAsAList', $AllowedDomains) @@ -299,7 +309,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -352,7 +366,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -379,6 +397,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.schema.mof index 14aaecce2e..f91ae23238 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFederationConfiguration/MSFT_TeamsFederationConfiguration.schema.mof @@ -15,4 +15,5 @@ class MSFT_TeamsFederationConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.psm1 index e902ca70c9..3bd7721982 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.psm1 @@ -52,7 +52,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -94,6 +98,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -162,7 +167,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -290,7 +299,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -415,7 +428,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.schema.mof index cc4896cc6c..a0f2a18be9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFeedbackPolicy/MSFT_TeamsFeedbackPolicy.schema.mof @@ -13,4 +13,5 @@ class MSFT_TeamsFeedbackPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 index 62af2c60f4..539e4f4ee5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.psm1 @@ -37,7 +37,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -75,6 +79,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -128,7 +133,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -241,7 +250,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -366,7 +379,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.schema.mof index 65d59f8b9e..a6916dcf07 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsFilesPolicy/MSFT_TeamsFilesPolicy.schema.mof @@ -9,4 +9,5 @@ class MSFT_TeamsFilesPolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.psm1 index 3e8ad626f1..7ab2957bbc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.psm1 @@ -44,7 +44,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' -InboundParameters $PSBoundParameters @@ -115,6 +119,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -174,7 +179,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -286,7 +295,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -337,7 +350,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $InformationPreference = 'Continue' $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' -InboundParameters $PSBoundParameters @@ -397,6 +414,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } #$results = Get-TargetResource @getParams $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.schema.mof index 4ab2928fbc..843fae438a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGroupPolicyAssignment/MSFT_TeamsGroupPolicyAssignment.schema.mof @@ -11,5 +11,5 @@ class MSFT_TeamsGroupPolicyAssignment : OMI_BaseResource [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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.psm1 index d0d0006666..b78bd59890 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.psm1 @@ -27,7 +27,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Guest Calling' @@ -62,6 +66,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return $result } @@ -105,7 +110,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Guest Calling' @@ -131,6 +140,7 @@ function Set-TargetResource $SetParams.Remove('ApplicationId') | Out-Null $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null if ($AllowPrivateCalling -ne $CurrentValues.AllowPrivateCalling) { @@ -167,7 +177,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -220,7 +234,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -247,6 +265,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.schema.mof index 3772c53927..3afdd7aebe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestCallingConfiguration/MSFT_TeamsGuestCallingConfiguration.schema.mof @@ -7,5 +7,5 @@ class MSFT_TeamsGuestCallingConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.psm1 index 519d9a1aae..60f8ca4e9b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.psm1 @@ -41,7 +41,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Guest Meeting settings' @@ -79,6 +83,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return $result } @@ -136,7 +141,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Guest Meeting settings' @@ -161,6 +170,7 @@ function Set-TargetResource $SetParams.Remove('ApplicationId') | Out-Null $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null Set-CsTeamsGuestMeetingConfiguration @SetParams } @@ -208,7 +218,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -261,7 +275,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -287,6 +305,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.schema.mof index e2e12a3836..98510798c3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMeetingConfiguration/MSFT_TeamsGuestMeetingConfiguration.schema.mof @@ -10,4 +10,5 @@ class MSFT_TeamsGuestMeetingConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.psm1 index 9127c65f31..a9d87c654f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.psm1 @@ -60,7 +60,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Guest Messaging settings' @@ -103,6 +107,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -178,7 +183,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Guest Messaging settings' @@ -191,6 +200,7 @@ function Set-TargetResource $inputValues.Remove('TenantId') | Out-Null $inputValues.Remove('CertificateThumbprint') | Out-Null $inputValues.Remove('Identity') | Out-Null + $inputValues.Remove('ManagedIdentity') | Out-Null foreach ($item in $inputValues) { if ([System.String]::IsNullOrEmpty($item.Value)) @@ -285,7 +295,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -338,7 +352,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -365,6 +383,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.schema.mof index 564f2024b2..68dd36fdaf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsGuestMessagingConfiguration/MSFT_TeamsGuestMessagingConfiguration.schema.mof @@ -15,5 +15,5 @@ class MSFT_TeamsGuestMessagingConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.psm1 index c2061ace70..9171d265f6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.psm1 @@ -59,7 +59,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -102,6 +106,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } return [System.Collections.Hashtable] $results } @@ -177,7 +182,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -312,7 +321,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. @@ -437,7 +450,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint - + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.schema.mof index e4fe6f5bc7..6293962713 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsIPPhonePolicy/MSFT_TeamsIPPhonePolicy.schema.mof @@ -14,4 +14,5 @@ class MSFT_TeamsIPPhonePolicy : OMI_BaseResource [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; }; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.psm1 index ee8427cd77..befd645d38 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.psm1 @@ -47,7 +47,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Meeting Broadcast' @@ -88,6 +92,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -150,7 +155,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Meeting Broadcast' @@ -175,6 +184,7 @@ function Set-TargetResource $SetParams.Remove('ApplicationId') | Out-Null $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null Set-CsTeamsMeetingBroadcastConfiguration @SetParams } @@ -228,7 +238,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -286,7 +300,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -313,6 +331,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } Add-ConfigurationDataEntry -Node 'NonNodeData' -Key 'SdnApiToken' -Value '**********'` -Description 'API Token for the Teams SDN Provider for Meeting Broadcast' diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.schema.mof index 52109ae99a..fdb7c10fb0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastConfiguration/MSFT_TeamsMeetingBroadcastConfiguration.schema.mof @@ -12,5 +12,5 @@ class MSFT_TeamsMeetingBroadcastConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.psm1 index 8210eeb73e..442fda7f9c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.psm1 @@ -45,7 +45,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting configuration of Teams Meeting Broadcast Policy {$Identity}" @@ -84,6 +88,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } return $nullReturn @@ -146,7 +151,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Setting configuration of Teams Meeting Broadcast Policy {$Identity}" @@ -189,6 +198,7 @@ function Set-TargetResource $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null $SetParams.Remove('Ensure') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null if ($Ensure -eq 'Present' -and $currentValues.Ensure -eq 'Absent') { @@ -251,7 +261,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -304,7 +318,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -336,6 +354,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } Write-Host " |---[$i/$($policies.Length)] $($policy.Identity)" -NoNewline $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.schema.mof index 5b4583b65d..6b21bfafc8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingBroadcastPolicy/MSFT_TeamsMeetingBroadcastPolicy.schema.mof @@ -11,5 +11,5 @@ class MSFT_TeamsMeetingBroadcastPolicy : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.psm1 index 20d7c924b9..726f895170 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.psm1 @@ -78,7 +78,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Getting configuration of Teams Meeting' @@ -125,6 +129,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -218,7 +223,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting configuration of Teams Meetings' @@ -243,6 +252,7 @@ function Set-TargetResource $SetParams.Remove('ApplicationId') | Out-Null $SetParams.Remove('TenantId') | Out-Null $SetParams.Remove('CertificateThumbprint') | Out-Null + $SetParams.Remove('ManagedIdentity') | Out-Null Set-CsTeamsMeetingConfiguration @SetParams } @@ -327,7 +337,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -380,7 +394,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` @@ -407,6 +425,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.schema.mof index 8855a61442..96b6f0e085 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingConfiguration/MSFT_TeamsMeetingConfiguration.schema.mof @@ -19,5 +19,5 @@ class MSFT_TeamsMeetingConfiguration : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.schema.mof index e5d68caeac8f4a1995916fffaa386014df5e2e9f..508e1f3cbaf1e580878a2a2c6251e918ea3673d6 100644 GIT binary patch delta 98 zcmaF#k#W&y#tpYBCUb}x$@?-SGUNeqIzuW$3WEZJCxZ)+Oak&Uf#T_t-h+9AH-0M}#>W+P2shD3%uAWmmUWk_LAVDMyc0g_2TUM5gH9mp (Connect-MgGraph) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/cross.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/check.png) | | *Security & Compliance Center* | ExchangeOnlineManagement
(Connect-IPPSSession) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/cross.png) | ![Cross](../../Images/cross.png) | | *SharePoint Online* | PnP.PowerShell
(Connect-PnPOnline) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/check.png) | -| *Teams* | MicrosoftTeams
(Connect-MicrosoftTeams) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/cross.png) | ![Cross](../../Images/cross.png) | ![Cross](../../Images/cross.png) | +| *Teams* | MicrosoftTeams
(Connect-MicrosoftTeams) | ![Check](../../Images/check.png) | ![Check](../../Images/check.png) | ![Cross](../../Images/cross.png) | ![Cross](../../Images/cross.png) | ![Check](../../Images/check.png) | > ![Check](../../Images/check.png) = Supported / ![Cross](../../Images/cross.png) = Not supported From 18c909f33fde9cda5e52a32f157993d7decfb3b1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 26 Jan 2024 07:18:06 -0500 Subject: [PATCH 020/171] Updates --- .../MSFT_TeamsTenantNetworkSite.psm1 | 4 ---- .../MSFT_TeamsWorkloadPolicy/MSFT_TeamsWorkloadPolicy.psm1 | 4 ---- 2 files changed, 8 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsTenantNetworkSite/MSFT_TeamsTenantNetworkSite.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsTenantNetworkSite/MSFT_TeamsTenantNetworkSite.psm1 index ed14c22491..19ae116587 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsTenantNetworkSite/MSFT_TeamsTenantNetworkSite.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsTenantNetworkSite/MSFT_TeamsTenantNetworkSite.psm1 @@ -402,10 +402,6 @@ function Export-TargetResource [System.String] $CertificateThumbprint, - [Parameter()] - [Switch] - $ManagedIdentity, - [Parameter()] [Switch] $ManagedIdentity diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsWorkloadPolicy/MSFT_TeamsWorkloadPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsWorkloadPolicy/MSFT_TeamsWorkloadPolicy.psm1 index 01989b313c..a19d66bff3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsWorkloadPolicy/MSFT_TeamsWorkloadPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsWorkloadPolicy/MSFT_TeamsWorkloadPolicy.psm1 @@ -389,10 +389,6 @@ function Export-TargetResource [System.String] $CertificateThumbprint, - [Parameter()] - [Switch] - $ManagedIdentity, - [Parameter()] [Switch] $ManagedIdentity From 3467f73fac906c1d0e1f877108f5549f341764bf Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Fri, 26 Jan 2024 12:33:44 +0000 Subject: [PATCH 021/171] Fix deletion of resource --- CHANGELOG.md | 6 ++++++ .../MSFT_TeamsEmergencyCallRoutingPolicy.psm1 | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 531a56fd91..eaae721e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* TeamsEmergencyCallRoutingPolicy + * Fix deletion of resource + FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) + # 1.24.124.1 * AADAuthenticationMethodPolicyAuthenticator diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 index 76e12f46e1..6afab26aab 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsEmergencyCallRoutingPolicy/MSFT_TeamsEmergencyCallRoutingPolicy.psm1 @@ -230,7 +230,7 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $CurrentValues.Ensure -eq 'Present') { Write-Verbose -Message "Removing existing Teams Meeting Policy {$Identity}" - Remove-CsTeamsEmergencyCallRoutingPolicy -Identity $Identity -Confirm:$false + Remove-CsTeamsEmergencyCallRoutingPolicy -Identity $Identity } } From 27045f66091277dd7ee3cd5a3317abc54bcd8f50 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 26 Jan 2024 13:13:52 +0000 Subject: [PATCH 022/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/teams/TeamsAppPermissionPolicy.md | 1 + docs/docs/resources/teams/TeamsAppSetupPolicy.md | 1 + docs/docs/resources/teams/TeamsAudioConferencingPolicy.md | 1 + docs/docs/resources/teams/TeamsCallHoldPolicy.md | 1 + docs/docs/resources/teams/TeamsCallParkPolicy.md | 1 + docs/docs/resources/teams/TeamsCallQueue.md | 1 + docs/docs/resources/teams/TeamsCallingPolicy.md | 1 + docs/docs/resources/teams/TeamsChannel.md | 1 + docs/docs/resources/teams/TeamsChannelTab.md | 1 + docs/docs/resources/teams/TeamsChannelsPolicy.md | 1 + docs/docs/resources/teams/TeamsClientConfiguration.md | 1 + docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md | 1 + docs/docs/resources/teams/TeamsCortanaPolicy.md | 1 + .../resources/teams/TeamsDialInConferencingTenantSettings.md | 1 + docs/docs/resources/teams/TeamsEmergencyCallRoutingPolicy.md | 1 + docs/docs/resources/teams/TeamsEmergencyCallingPolicy.md | 1 + docs/docs/resources/teams/TeamsEnhancedEncryptionPolicy.md | 1 + docs/docs/resources/teams/TeamsEventsPolicy.md | 1 + docs/docs/resources/teams/TeamsFederationConfiguration.md | 1 + docs/docs/resources/teams/TeamsFeedbackPolicy.md | 1 + docs/docs/resources/teams/TeamsFilesPolicy.md | 1 + docs/docs/resources/teams/TeamsGroupPolicyAssignment.md | 1 + docs/docs/resources/teams/TeamsGuestCallingConfiguration.md | 1 + docs/docs/resources/teams/TeamsGuestMeetingConfiguration.md | 1 + docs/docs/resources/teams/TeamsGuestMessagingConfiguration.md | 1 + docs/docs/resources/teams/TeamsIPPhonePolicy.md | 1 + docs/docs/resources/teams/TeamsMeetingBroadcastConfiguration.md | 1 + docs/docs/resources/teams/TeamsMeetingBroadcastPolicy.md | 1 + docs/docs/resources/teams/TeamsMeetingConfiguration.md | 1 + docs/docs/resources/teams/TeamsMeetingPolicy.md | 1 + docs/docs/resources/teams/TeamsMessagingPolicy.md | 1 + docs/docs/resources/teams/TeamsMobilityPolicy.md | 1 + docs/docs/resources/teams/TeamsNetworkRoamingPolicy.md | 1 + docs/docs/resources/teams/TeamsOnlineVoiceUser.md | 1 + docs/docs/resources/teams/TeamsOnlineVoicemailPolicy.md | 1 + docs/docs/resources/teams/TeamsOnlineVoicemailUserSettings.md | 1 + docs/docs/resources/teams/TeamsOrgWideAppSettings.md | 1 + docs/docs/resources/teams/TeamsPstnUsage.md | 1 + docs/docs/resources/teams/TeamsShiftsPolicy.md | 1 + docs/docs/resources/teams/TeamsTeam.md | 1 + docs/docs/resources/teams/TeamsTemplatesPolicy.md | 1 + docs/docs/resources/teams/TeamsTenantDialPlan.md | 1 + docs/docs/resources/teams/TeamsTenantNetworkRegion.md | 1 + docs/docs/resources/teams/TeamsTenantNetworkSite.md | 1 + docs/docs/resources/teams/TeamsTenantNetworkSubnet.md | 1 + docs/docs/resources/teams/TeamsTenantTrustedIPAddress.md | 1 + docs/docs/resources/teams/TeamsTranslationRule.md | 1 + docs/docs/resources/teams/TeamsUnassignedNumberTreatment.md | 1 + docs/docs/resources/teams/TeamsUpdateManagementPolicy.md | 1 + docs/docs/resources/teams/TeamsUpgradeConfiguration.md | 1 + docs/docs/resources/teams/TeamsUpgradePolicy.md | 1 + docs/docs/resources/teams/TeamsUser.md | 1 + docs/docs/resources/teams/TeamsUserCallingSettings.md | 1 + docs/docs/resources/teams/TeamsUserPolicyAssignment.md | 1 + docs/docs/resources/teams/TeamsVdiPolicy.md | 1 + docs/docs/resources/teams/TeamsVoiceRoute.md | 1 + docs/docs/resources/teams/TeamsVoiceRoutingPolicy.md | 1 + docs/docs/resources/teams/TeamsWorkloadPolicy.md | 1 + 58 files changed, 58 insertions(+) diff --git a/docs/docs/resources/teams/TeamsAppPermissionPolicy.md b/docs/docs/resources/teams/TeamsAppPermissionPolicy.md index 964b8afe99..adea192f37 100644 --- a/docs/docs/resources/teams/TeamsAppPermissionPolicy.md +++ b/docs/docs/resources/teams/TeamsAppPermissionPolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsAppSetupPolicy.md b/docs/docs/resources/teams/TeamsAppSetupPolicy.md index 84b58adb0b..4b367832d3 100644 --- a/docs/docs/resources/teams/TeamsAppSetupPolicy.md +++ b/docs/docs/resources/teams/TeamsAppSetupPolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsAudioConferencingPolicy.md b/docs/docs/resources/teams/TeamsAudioConferencingPolicy.md index 1e95f04a16..58aa90102e 100644 --- a/docs/docs/resources/teams/TeamsAudioConferencingPolicy.md +++ b/docs/docs/resources/teams/TeamsAudioConferencingPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsCallHoldPolicy.md b/docs/docs/resources/teams/TeamsCallHoldPolicy.md index 11659cc00a..58c8c000f3 100644 --- a/docs/docs/resources/teams/TeamsCallHoldPolicy.md +++ b/docs/docs/resources/teams/TeamsCallHoldPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsCallParkPolicy.md b/docs/docs/resources/teams/TeamsCallParkPolicy.md index c5ead27b46..2ae81d96be 100644 --- a/docs/docs/resources/teams/TeamsCallParkPolicy.md +++ b/docs/docs/resources/teams/TeamsCallParkPolicy.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsCallQueue.md b/docs/docs/resources/teams/TeamsCallQueue.md index 485d73fe4b..6c93ecf12f 100644 --- a/docs/docs/resources/teams/TeamsCallQueue.md +++ b/docs/docs/resources/teams/TeamsCallQueue.md @@ -57,6 +57,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsCallingPolicy.md b/docs/docs/resources/teams/TeamsCallingPolicy.md index f316b2c8a1..53978c5ba9 100644 --- a/docs/docs/resources/teams/TeamsCallingPolicy.md +++ b/docs/docs/resources/teams/TeamsCallingPolicy.md @@ -30,6 +30,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsChannel.md b/docs/docs/resources/teams/TeamsChannel.md index 58fb5741f4..2377089868 100644 --- a/docs/docs/resources/teams/TeamsChannel.md +++ b/docs/docs/resources/teams/TeamsChannel.md @@ -14,6 +14,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsChannelTab.md b/docs/docs/resources/teams/TeamsChannelTab.md index 928df670ae..2c232a3b26 100644 --- a/docs/docs/resources/teams/TeamsChannelTab.md +++ b/docs/docs/resources/teams/TeamsChannelTab.md @@ -19,6 +19,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsChannelsPolicy.md b/docs/docs/resources/teams/TeamsChannelsPolicy.md index 04569feb57..279c5730af 100644 --- a/docs/docs/resources/teams/TeamsChannelsPolicy.md +++ b/docs/docs/resources/teams/TeamsChannelsPolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsClientConfiguration.md b/docs/docs/resources/teams/TeamsClientConfiguration.md index d103786a7f..091eb128b1 100644 --- a/docs/docs/resources/teams/TeamsClientConfiguration.md +++ b/docs/docs/resources/teams/TeamsClientConfiguration.md @@ -23,6 +23,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md b/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md index 26161a2add..c82b70a65f 100644 --- a/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md +++ b/docs/docs/resources/teams/TeamsComplianceRecordingPolicy.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsCortanaPolicy.md b/docs/docs/resources/teams/TeamsCortanaPolicy.md index 5a839ca4d3..1662b06d23 100644 --- a/docs/docs/resources/teams/TeamsCortanaPolicy.md +++ b/docs/docs/resources/teams/TeamsCortanaPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsDialInConferencingTenantSettings.md b/docs/docs/resources/teams/TeamsDialInConferencingTenantSettings.md index abd82e30cb..3dfe805be0 100644 --- a/docs/docs/resources/teams/TeamsDialInConferencingTenantSettings.md +++ b/docs/docs/resources/teams/TeamsDialInConferencingTenantSettings.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | # TeamsUserCallingSettings diff --git a/docs/docs/resources/teams/TeamsEmergencyCallRoutingPolicy.md b/docs/docs/resources/teams/TeamsEmergencyCallRoutingPolicy.md index fab9c4562a..bbc4015b73 100644 --- a/docs/docs/resources/teams/TeamsEmergencyCallRoutingPolicy.md +++ b/docs/docs/resources/teams/TeamsEmergencyCallRoutingPolicy.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ### MSFT_TeamsEmergencyNumber diff --git a/docs/docs/resources/teams/TeamsEmergencyCallingPolicy.md b/docs/docs/resources/teams/TeamsEmergencyCallingPolicy.md index 659bd3f1a2..9acf97d8f0 100644 --- a/docs/docs/resources/teams/TeamsEmergencyCallingPolicy.md +++ b/docs/docs/resources/teams/TeamsEmergencyCallingPolicy.md @@ -16,6 +16,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsEnhancedEncryptionPolicy.md b/docs/docs/resources/teams/TeamsEnhancedEncryptionPolicy.md index 3c6252cb3e..6936115dad 100644 --- a/docs/docs/resources/teams/TeamsEnhancedEncryptionPolicy.md +++ b/docs/docs/resources/teams/TeamsEnhancedEncryptionPolicy.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsEventsPolicy.md b/docs/docs/resources/teams/TeamsEventsPolicy.md index d9b751fec2..3191a689fa 100644 --- a/docs/docs/resources/teams/TeamsEventsPolicy.md +++ b/docs/docs/resources/teams/TeamsEventsPolicy.md @@ -21,6 +21,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsFederationConfiguration.md b/docs/docs/resources/teams/TeamsFederationConfiguration.md index 19942ea24c..90e9481a2f 100644 --- a/docs/docs/resources/teams/TeamsFederationConfiguration.md +++ b/docs/docs/resources/teams/TeamsFederationConfiguration.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsFeedbackPolicy.md b/docs/docs/resources/teams/TeamsFeedbackPolicy.md index d0c7c3c845..e85811f97d 100644 --- a/docs/docs/resources/teams/TeamsFeedbackPolicy.md +++ b/docs/docs/resources/teams/TeamsFeedbackPolicy.md @@ -16,6 +16,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsFilesPolicy.md b/docs/docs/resources/teams/TeamsFilesPolicy.md index 1bd8c17558..e9986b58a8 100644 --- a/docs/docs/resources/teams/TeamsFilesPolicy.md +++ b/docs/docs/resources/teams/TeamsFilesPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsGroupPolicyAssignment.md b/docs/docs/resources/teams/TeamsGroupPolicyAssignment.md index 8743770292..6bab7bfdd3 100644 --- a/docs/docs/resources/teams/TeamsGroupPolicyAssignment.md +++ b/docs/docs/resources/teams/TeamsGroupPolicyAssignment.md @@ -14,6 +14,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsGuestCallingConfiguration.md b/docs/docs/resources/teams/TeamsGuestCallingConfiguration.md index 13408c8e25..9f72539d71 100644 --- a/docs/docs/resources/teams/TeamsGuestCallingConfiguration.md +++ b/docs/docs/resources/teams/TeamsGuestCallingConfiguration.md @@ -10,6 +10,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsGuestMeetingConfiguration.md b/docs/docs/resources/teams/TeamsGuestMeetingConfiguration.md index 5ecba7f55f..5aad313ee1 100644 --- a/docs/docs/resources/teams/TeamsGuestMeetingConfiguration.md +++ b/docs/docs/resources/teams/TeamsGuestMeetingConfiguration.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsGuestMessagingConfiguration.md b/docs/docs/resources/teams/TeamsGuestMessagingConfiguration.md index c37379f7ef..0e2e710589 100644 --- a/docs/docs/resources/teams/TeamsGuestMessagingConfiguration.md +++ b/docs/docs/resources/teams/TeamsGuestMessagingConfiguration.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsIPPhonePolicy.md b/docs/docs/resources/teams/TeamsIPPhonePolicy.md index 7821f34895..33c3137d97 100644 --- a/docs/docs/resources/teams/TeamsIPPhonePolicy.md +++ b/docs/docs/resources/teams/TeamsIPPhonePolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMeetingBroadcastConfiguration.md b/docs/docs/resources/teams/TeamsMeetingBroadcastConfiguration.md index 4a642c8b81..a8aa7c45fc 100644 --- a/docs/docs/resources/teams/TeamsMeetingBroadcastConfiguration.md +++ b/docs/docs/resources/teams/TeamsMeetingBroadcastConfiguration.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMeetingBroadcastPolicy.md b/docs/docs/resources/teams/TeamsMeetingBroadcastPolicy.md index f6f4d23f1e..51d09e22e0 100644 --- a/docs/docs/resources/teams/TeamsMeetingBroadcastPolicy.md +++ b/docs/docs/resources/teams/TeamsMeetingBroadcastPolicy.md @@ -14,6 +14,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMeetingConfiguration.md b/docs/docs/resources/teams/TeamsMeetingConfiguration.md index fd463d1e0c..e72dbf2ef4 100644 --- a/docs/docs/resources/teams/TeamsMeetingConfiguration.md +++ b/docs/docs/resources/teams/TeamsMeetingConfiguration.md @@ -22,6 +22,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMeetingPolicy.md b/docs/docs/resources/teams/TeamsMeetingPolicy.md index f57fe2d437..ae74df5e1e 100644 --- a/docs/docs/resources/teams/TeamsMeetingPolicy.md +++ b/docs/docs/resources/teams/TeamsMeetingPolicy.md @@ -72,6 +72,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMessagingPolicy.md b/docs/docs/resources/teams/TeamsMessagingPolicy.md index 69389222c9..34b002a9a9 100644 --- a/docs/docs/resources/teams/TeamsMessagingPolicy.md +++ b/docs/docs/resources/teams/TeamsMessagingPolicy.md @@ -35,6 +35,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsMobilityPolicy.md b/docs/docs/resources/teams/TeamsMobilityPolicy.md index cf1b238da7..885d5d5180 100644 --- a/docs/docs/resources/teams/TeamsMobilityPolicy.md +++ b/docs/docs/resources/teams/TeamsMobilityPolicy.md @@ -14,6 +14,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsNetworkRoamingPolicy.md b/docs/docs/resources/teams/TeamsNetworkRoamingPolicy.md index 7bd09020d3..459a8c1e19 100644 --- a/docs/docs/resources/teams/TeamsNetworkRoamingPolicy.md +++ b/docs/docs/resources/teams/TeamsNetworkRoamingPolicy.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsOnlineVoiceUser.md b/docs/docs/resources/teams/TeamsOnlineVoiceUser.md index 885a3bcd2b..1ffbdd96a4 100644 --- a/docs/docs/resources/teams/TeamsOnlineVoiceUser.md +++ b/docs/docs/resources/teams/TeamsOnlineVoiceUser.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsOnlineVoicemailPolicy.md b/docs/docs/resources/teams/TeamsOnlineVoicemailPolicy.md index 9d5dcb4d6b..d66f177c39 100644 --- a/docs/docs/resources/teams/TeamsOnlineVoicemailPolicy.md +++ b/docs/docs/resources/teams/TeamsOnlineVoicemailPolicy.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | # TeamsOnlinceVoicemailPolicy diff --git a/docs/docs/resources/teams/TeamsOnlineVoicemailUserSettings.md b/docs/docs/resources/teams/TeamsOnlineVoicemailUserSettings.md index 4109f0bb3e..b783b80581 100644 --- a/docs/docs/resources/teams/TeamsOnlineVoicemailUserSettings.md +++ b/docs/docs/resources/teams/TeamsOnlineVoicemailUserSettings.md @@ -20,6 +20,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsOrgWideAppSettings.md b/docs/docs/resources/teams/TeamsOrgWideAppSettings.md index 74a36a0688..77ca71aa99 100644 --- a/docs/docs/resources/teams/TeamsOrgWideAppSettings.md +++ b/docs/docs/resources/teams/TeamsOrgWideAppSettings.md @@ -7,6 +7,7 @@ | **IsSingleInstance** | Key | String | Specifies the resource is a single instance, the value must be 'Yes' | `Yes` | | **IsSideloadedAppsInteractionEnabled** | Write | Boolean | Determines whether or not to allow interaction with custom apps. | | | **Credential** | Write | PSCredential | Credentials of the Teams Admin | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | # TeamsOgWideAppSettings diff --git a/docs/docs/resources/teams/TeamsPstnUsage.md b/docs/docs/resources/teams/TeamsPstnUsage.md index 2393755e3c..2249dddfb7 100644 --- a/docs/docs/resources/teams/TeamsPstnUsage.md +++ b/docs/docs/resources/teams/TeamsPstnUsage.md @@ -10,6 +10,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsShiftsPolicy.md b/docs/docs/resources/teams/TeamsShiftsPolicy.md index d7dc1079f8..e03377d512 100644 --- a/docs/docs/resources/teams/TeamsShiftsPolicy.md +++ b/docs/docs/resources/teams/TeamsShiftsPolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTeam.md b/docs/docs/resources/teams/TeamsTeam.md index 50460212f8..d45236e6ea 100644 --- a/docs/docs/resources/teams/TeamsTeam.md +++ b/docs/docs/resources/teams/TeamsTeam.md @@ -32,6 +32,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTemplatesPolicy.md b/docs/docs/resources/teams/TeamsTemplatesPolicy.md index f1b609f984..ae5e4dc6bd 100644 --- a/docs/docs/resources/teams/TeamsTemplatesPolicy.md +++ b/docs/docs/resources/teams/TeamsTemplatesPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTenantDialPlan.md b/docs/docs/resources/teams/TeamsTenantDialPlan.md index aedc6c19ba..81fa2c6813 100644 --- a/docs/docs/resources/teams/TeamsTenantDialPlan.md +++ b/docs/docs/resources/teams/TeamsTenantDialPlan.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ### MSFT_TeamsVoiceNormalizationRule diff --git a/docs/docs/resources/teams/TeamsTenantNetworkRegion.md b/docs/docs/resources/teams/TeamsTenantNetworkRegion.md index a3f7317a76..4800c0f10c 100644 --- a/docs/docs/resources/teams/TeamsTenantNetworkRegion.md +++ b/docs/docs/resources/teams/TeamsTenantNetworkRegion.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTenantNetworkSite.md b/docs/docs/resources/teams/TeamsTenantNetworkSite.md index 276cebed6b..40ce3739c5 100644 --- a/docs/docs/resources/teams/TeamsTenantNetworkSite.md +++ b/docs/docs/resources/teams/TeamsTenantNetworkSite.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTenantNetworkSubnet.md b/docs/docs/resources/teams/TeamsTenantNetworkSubnet.md index 06c5ecf19a..a4455fe902 100644 --- a/docs/docs/resources/teams/TeamsTenantNetworkSubnet.md +++ b/docs/docs/resources/teams/TeamsTenantNetworkSubnet.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTenantTrustedIPAddress.md b/docs/docs/resources/teams/TeamsTenantTrustedIPAddress.md index 49ffa4a573..627539400b 100644 --- a/docs/docs/resources/teams/TeamsTenantTrustedIPAddress.md +++ b/docs/docs/resources/teams/TeamsTenantTrustedIPAddress.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsTranslationRule.md b/docs/docs/resources/teams/TeamsTranslationRule.md index 5bf465ca20..723c968fa6 100644 --- a/docs/docs/resources/teams/TeamsTranslationRule.md +++ b/docs/docs/resources/teams/TeamsTranslationRule.md @@ -13,6 +13,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUnassignedNumberTreatment.md b/docs/docs/resources/teams/TeamsUnassignedNumberTreatment.md index bc15a85cfe..6c111e8968 100644 --- a/docs/docs/resources/teams/TeamsUnassignedNumberTreatment.md +++ b/docs/docs/resources/teams/TeamsUnassignedNumberTreatment.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUpdateManagementPolicy.md b/docs/docs/resources/teams/TeamsUpdateManagementPolicy.md index 1469929ee9..7451fa8b04 100644 --- a/docs/docs/resources/teams/TeamsUpdateManagementPolicy.md +++ b/docs/docs/resources/teams/TeamsUpdateManagementPolicy.md @@ -18,6 +18,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUpgradeConfiguration.md b/docs/docs/resources/teams/TeamsUpgradeConfiguration.md index 2a7f55b508..e1c9634998 100644 --- a/docs/docs/resources/teams/TeamsUpgradeConfiguration.md +++ b/docs/docs/resources/teams/TeamsUpgradeConfiguration.md @@ -11,6 +11,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUpgradePolicy.md b/docs/docs/resources/teams/TeamsUpgradePolicy.md index 2066af5abd..0e6b95be61 100644 --- a/docs/docs/resources/teams/TeamsUpgradePolicy.md +++ b/docs/docs/resources/teams/TeamsUpgradePolicy.md @@ -11,6 +11,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUser.md b/docs/docs/resources/teams/TeamsUser.md index 895db84834..b8bd4bfd5c 100644 --- a/docs/docs/resources/teams/TeamsUser.md +++ b/docs/docs/resources/teams/TeamsUser.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUserCallingSettings.md b/docs/docs/resources/teams/TeamsUserCallingSettings.md index 21ad05c299..369c7b6078 100644 --- a/docs/docs/resources/teams/TeamsUserCallingSettings.md +++ b/docs/docs/resources/teams/TeamsUserCallingSettings.md @@ -18,6 +18,7 @@ | **ForwardingTarget** | Write | String | The forwarding target. Supported types of values are ObjectId's, SIP addresses and phone numbers. For phone numbers we support the following types of formats: E.164 (+12065551234 or +1206555000;ext=1234) or non-E.164 like 1234. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Required | PSCredential | Credentials of the Teams Global Admin. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsUserPolicyAssignment.md b/docs/docs/resources/teams/TeamsUserPolicyAssignment.md index d7ec987d99..46de0d3eb6 100644 --- a/docs/docs/resources/teams/TeamsUserPolicyAssignment.md +++ b/docs/docs/resources/teams/TeamsUserPolicyAssignment.md @@ -31,6 +31,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | # TeamsUserAssignmentPolicy diff --git a/docs/docs/resources/teams/TeamsVdiPolicy.md b/docs/docs/resources/teams/TeamsVdiPolicy.md index 5bf7a9b8d3..0cf0a7655d 100644 --- a/docs/docs/resources/teams/TeamsVdiPolicy.md +++ b/docs/docs/resources/teams/TeamsVdiPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsVoiceRoute.md b/docs/docs/resources/teams/TeamsVoiceRoute.md index 5da9a6af95..f194d9db01 100644 --- a/docs/docs/resources/teams/TeamsVoiceRoute.md +++ b/docs/docs/resources/teams/TeamsVoiceRoute.md @@ -15,6 +15,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsVoiceRoutingPolicy.md b/docs/docs/resources/teams/TeamsVoiceRoutingPolicy.md index 0194070790..96252959c4 100644 --- a/docs/docs/resources/teams/TeamsVoiceRoutingPolicy.md +++ b/docs/docs/resources/teams/TeamsVoiceRoutingPolicy.md @@ -12,6 +12,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description diff --git a/docs/docs/resources/teams/TeamsWorkloadPolicy.md b/docs/docs/resources/teams/TeamsWorkloadPolicy.md index 4b7588a542..bfa304ab20 100644 --- a/docs/docs/resources/teams/TeamsWorkloadPolicy.md +++ b/docs/docs/resources/teams/TeamsWorkloadPolicy.md @@ -17,6 +17,7 @@ | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | | **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | | **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | ## Description From 881b4ffddde70d9fc3de0810bd5d39d7b02730eb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Sun, 28 Jan 2024 08:59:09 -0500 Subject: [PATCH 023/171] Fixed EXO Integration Tests --- CHANGELOG.md | 2 +- .../MSFT_EXOOnPremisesOrganization.psm1 | 8 ++++-- .../MSFT_EXOPartnerApplication.psm1 | 16 ++++++++--- .../Dependencies/Manifest.psd1 | 2 +- .../1-Create.ps1 | 3 ++- .../2-Update.ps1 | 2 +- .../3-Remove.ps1 | 3 ++- .../EXODataEncryptionPolicy/1-Create.ps1 | 27 ------------------- .../EXODataEncryptionPolicy/2-Update.ps1 | 27 ------------------- .../EXODistributionGroup/1-Create.ps1 | 2 +- .../EXODistributionGroup/2-Update.ps1 | 2 +- .../EXODkimSigningConfig/1-Create.ps1 | 3 ++- .../EXODkimSigningConfig/2-Update.ps1 | 3 ++- .../EXODkimSigningConfig/3-Remove.ps1 | 3 ++- .../EXOGlobalAddressList/1-Create.ps1 | 1 + .../EXOHostedContentFilterPolicy/1-Create.ps1 | 2 +- .../EXOHostedContentFilterPolicy/2-Update.ps1 | 2 +- .../EXOHostedContentFilterRule/1-Create.ps1 | 5 ++-- .../EXOHostedContentFilterRule/2-Update.ps1 | 5 ++-- .../EXOHostedContentFilterRule/3-Remove.ps1 | 2 +- .../1-Create.ps1 | 4 ++- .../2-Update.ps1 | 4 ++- .../3-Remove.ps1 | 1 + .../EXOInboundConnector/1-Create.ps1 | 9 +++---- .../EXOInboundConnector/2-Update.ps1 | 9 +++---- .../EXOInboundConnector/3-Remove.ps1 | 2 +- .../Resources/EXOMailContact/1-Create.ps1 | 2 +- .../Resources/EXOMailContact/2-Update.ps1 | 2 +- .../Resources/EXOMailContact/3-Remove.ps1 | 2 +- .../EXOManagementRoleAssignment/1-Create.ps1 | 3 ++- .../EXOManagementRoleAssignment/2-Update.ps1 | 3 ++- .../EXOManagementRoleAssignment/3-Remove.ps1 | 3 ++- .../EXOOnPremisesOrganization/1-Create.ps1 | 13 ++++----- .../EXOOutboundConnector/1-Create.ps1 | 12 ++++----- .../EXOOutboundConnector/2-Update.ps1 | 14 +++++----- .../EXOPartnerApplication/1-Create.ps1 | 1 - .../EXOPartnerApplication/2-Update.ps1 | 1 - .../Examples/Resources/EXOPlace/1-Create.ps1 | 4 +-- .../Examples/Resources/EXOPlace/2-Update.ps1 | 2 +- .../Examples/Resources/EXOPlace/3-Remove.ps1 | 2 +- .../Resources/EXORemoteDomain/1-Create.ps1 | 2 +- .../Resources/EXORemoteDomain/2-Update.ps1 | 2 +- .../EXOSafeAttachmentRule/1-Create.ps1 | 4 +-- .../EXOSafeAttachmentRule/2-Update.ps1 | 4 +-- .../Resources/EXOSafeLinksRule/1-Create.ps1 | 4 +-- .../Resources/EXOSafeLinksRule/2-Update.ps1 | 4 +-- .../Resources/EXOSharedMailbox/1-Create.ps1 | 7 ++--- .../Resources/EXOSharedMailbox/2-Update.ps1 | 7 ++--- .../Resources/EXOSharedMailbox/3-Remove.ps1 | 7 ++--- .../Resources/EXOTransportRule/1-Create.ps1 | 8 +++--- .../Resources/EXOTransportRule/2-Update.ps1 | 12 ++++----- 51 files changed, 124 insertions(+), 150 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/2-Update.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index f9fd1eea6d..153396122d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ * TEAMS * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES - * Updated MSCloudLoginAssistant dependencies to version 1.1.9. + * Updated MSCloudLoginAssistant dependencies to version 1.1.10. # 1.24.124.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOnPremisesOrganization/MSFT_EXOOnPremisesOrganization.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOnPremisesOrganization/MSFT_EXOOnPremisesOrganization.psm1 index 8eac15297c..c2c6ed8690 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOnPremisesOrganization/MSFT_EXOOnPremisesOrganization.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOnPremisesOrganization/MSFT_EXOOnPremisesOrganization.psm1 @@ -243,7 +243,6 @@ function Set-TargetResource InboundConnector = $InboundConnector OrganizationName = $OrganizationName OrganizationGuid = $OrganizationGuid - OrganizationRelationship = $OrganizationRelationship OutboundConnector = $OutboundConnector Confirm = $false } @@ -254,11 +253,16 @@ function Set-TargetResource HybridDomains = $HybridDomains InboundConnector = $InboundConnector OrganizationName = $OrganizationName - OrganizationRelationship = $OrganizationRelationship OutboundConnector = $OutboundConnector Confirm = $false } + if (-not [System.String]::IsNullOrEmpty($OrganizationRelationship)) + { + $NewOnPremisesOrganizationParams.Add('OrganizationRelationship', $OrganizationRelationship) + $SetOnPremisesOrganizationParams.Add('OrganizationRelationship', $OrganizationRelationship) + } + # CASE: On-premises Organization doesn't exist but should; if ($Ensure -eq 'Present' -and $currentOnPremisesOrganizationConfig.Ensure -eq 'Absent') { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPartnerApplication/MSFT_EXOPartnerApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPartnerApplication/MSFT_EXOPartnerApplication.psm1 index 1916175cc0..86c8272b25 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPartnerApplication/MSFT_EXOPartnerApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPartnerApplication/MSFT_EXOPartnerApplication.psm1 @@ -224,9 +224,7 @@ function Set-TargetResource Name = $Name ApplicationIdentifier = $ApplicationIdentifier AcceptSecurityIdentifierInformation = $AcceptSecurityIdentifierInformation - AccountType = $AccountType Enabled = $Enabled - LinkedAccount = $LinkedAccount Confirm = $false } @@ -235,12 +233,22 @@ function Set-TargetResource Name = $Name ApplicationIdentifier = $ApplicationIdentifier AcceptSecurityIdentifierInformation = $AcceptSecurityIdentifierInformation - AccountType = $AccountType Enabled = $Enabled - LinkedAccount = $LinkedAccount Confirm = $false } + if (-not [System.String]::IsNullOrEmpty($AccountType)) + { + $NewPartnerApplicationParams.Add('AccountType', $AccountType) + $SetPartnerApplicationParams.Add('AccountType', $AccountType) + } + + if (-not [System.String]::IsNullOrEmpty($LinkedAccount)) + { + $NewPartnerApplicationParams.Add('LinkedAccount', $LinkedAccount) + $SetPartnerApplicationParams.Add('LinkedAccount', $LinkedAccount) + } + # CASE: Partner Application doesn't exist but should; if ($Ensure -eq 'Present' -and $currentPartnerApplicationConfig.Ensure -eq 'Absent') { diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 9beaea7c74..9cc63defeb 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -86,7 +86,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.9" + RequiredVersion = "1.1.10" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 index 0fb2f2f613..1d2cade88f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 @@ -7,11 +7,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Block Basic Auth" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 index 878bf3ebe1..68e77e5d2b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 @@ -12,7 +12,7 @@ Configuration Example { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Test Policy" # Updaqted Property Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 index becf7194b5..f1e7abdcd2 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 @@ -7,11 +7,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Test Policy" Ensure = "Absent" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/1-Create.ps1 deleted file mode 100644 index 4f7d7e5e58..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/1-Create.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -<# -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(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXODataEncryptionPolicy 'ConfigureDataEncryptionPolicy' - { - Identity = 'US Mailboxes' - Name = 'All US Mailboxes' - Description = 'All Mailboxes of users in the US' - Enabled = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/2-Update.ps1 deleted file mode 100644 index b9f21cf1a7..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODataEncryptionPolicy/2-Update.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -<# -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(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXODataEncryptionPolicy 'ConfigureDataEncryptionPolicy' - { - Identity = 'US Mailboxes' - Name = 'All US Mailboxes' - Description = 'All Mailboxes of users in the US. Updated' # Updated Property - Enabled = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 index 7b5327e6d2..adcbd23b3a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 @@ -31,7 +31,7 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain"; + OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 index 2e59ecff8e..997f790410 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 @@ -31,7 +31,7 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain"; + OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/1-Create.ps1 index 76dca250e0..5f427b2eaa 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/1-Create.ps1 @@ -12,12 +12,13 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { KeySize = 1024 - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain HeaderCanonicalization = "Relaxed" Enabled = $True BodyCanonicalization = "Relaxed" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/2-Update.ps1 index f9d8760554..519d24fe0a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/2-Update.ps1 @@ -12,12 +12,13 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { KeySize = 1024 - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain HeaderCanonicalization = "Relaxed" Enabled = $False # Updated Property BodyCanonicalization = "Relaxed" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/3-Remove.ps1 index 39c018e8b5..c37c0a7f6f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODkimSigningConfig/3-Remove.ps1 @@ -12,11 +12,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain Ensure = "Absent" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOGlobalAddressList/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOGlobalAddressList/1-Create.ps1 index 88f004d8e2..8434d79874 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOGlobalAddressList/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOGlobalAddressList/1-Create.ps1 @@ -21,6 +21,7 @@ Configuration Example ConditionalCompany = "Contoso" ConditionalDepartment = "Human Resources" ConditionalStateOrProvince = "Washington" + IncludedRecipients = 'AllRecipients' Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 index 8ad924b9f0..fd0ffdf943 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 @@ -36,7 +36,7 @@ Configuration Example IncreaseScoreWithRedirectToOtherPort = "Off" InlineSafetyTipsEnabled = $True LanguageBlockList = @() - MakeDefault = $True + MakeDefault = $False MarkAsSpamBulkMail = "On" MarkAsSpamEmbedTagsInHtml = "Off" MarkAsSpamEmptyMessages = "Off" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 index 68f54d10fd..ffecda1e04 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 @@ -36,7 +36,7 @@ Configuration Example IncreaseScoreWithRedirectToOtherPort = "Off" InlineSafetyTipsEnabled = $True LanguageBlockList = @() - MakeDefault = $True + MakeDefault = $False MarkAsSpamBulkMail = "On" MarkAsSpamEmbedTagsInHtml = "Off" MarkAsSpamEmptyMessages = "Off" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 index 304e2d1e99..d8f53e8694 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 @@ -17,10 +17,11 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Contoso Human Resources" + ExceptIfSentToMemberOf = "Legal Team" + RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 index 4c0bbf0035..602414c835 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 @@ -17,10 +17,11 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Contoso Human Resources" + ExceptIfSentToMemberOf = "Legal Team" + RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/3-Remove.ps1 index 4af57b4f29..46aa815857 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/3-Remove.ps1 @@ -17,7 +17,7 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" HostedContentFilterPolicy = "Integration CFP" Ensure = "Absent" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 index b2680a0974..9a861d1108 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' @@ -20,7 +21,8 @@ Configuration Example Identity = "Contoso Executives" Comments = "Does not apply to Executives" Enabled = $True - ExceptIfFrom = "John Smith" + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = 'Executives' HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 index 4d7ae70dd0..36f324d0b3 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' @@ -20,7 +21,8 @@ Configuration Example Identity = "Contoso Executives" Comments = "Does not apply to Executives" Enabled = $False # Updated Property - ExceptIfFrom = "John Smith" + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = 'Executives' HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/3-Remove.ps1 index fd568fae34..261f1ffc0e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/3-Remove.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/1-Create.ps1 index a08678dd8b..e8524e45e6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/1-Create.ps1 @@ -17,16 +17,15 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" - CloudServicesMailEnabled = $True - Comment = "Inbound connector for Contoso" + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True RequireTls = $True SenderDomains = "*.contoso.com" TlsSenderCertificateName = "contoso.com" - TreatMessagesAsInternal = $True Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/2-Update.ps1 index 7a38b9078b..07c3c4cabd 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/2-Update.ps1 @@ -17,16 +17,15 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" - CloudServicesMailEnabled = $True - Comment = "Inbound connector for Contoso" + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $False # Updated Property RequireTls = $True SenderDomains = "*.contoso.com" TlsSenderCertificateName = "contoso.com" - TreatMessagesAsInternal = $True Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/3-Remove.ps1 index 974357ff51..9b30be3986 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOInboundConnector/3-Remove.ps1 @@ -17,7 +17,7 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" + Identity = "Integration Inbound Connector" Ensure = "Absent" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/1-Create.ps1 index a4577146ab..6a804d5c63 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/1-Create.ps1 @@ -28,7 +28,7 @@ Configuration Example ModeratedBy = @() ModerationEnabled = $false Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $true CustomAttribute1 = 'Custom Value 1' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/2-Update.ps1 index c9b69b8bec..d6dae3e389 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/2-Update.ps1 @@ -28,7 +28,7 @@ Configuration Example ModeratedBy = @() ModerationEnabled = $false Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $false # Updated Property CustomAttribute1 = 'Custom Value 1' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/3-Remove.ps1 index f84f309064..9c00cbf291 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailContact/3-Remove.ps1 @@ -23,7 +23,7 @@ Configuration Example Ensure = 'Absent' ExternalEmailAddress = 'SMTP:test@tailspintoys.com' Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $false # Updated Property CustomAttribute1 = 'Custom Value 1' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/1-Create.ps1 index aee17ea1b5..38bf4d1041 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/1-Create.ps1 @@ -12,6 +12,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -20,7 +21,7 @@ Configuration Example Ensure = "Present"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AdeleV"; + User = "AdeleV@$Domain"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/2-Update.ps1 index 76465f6366..9737099842 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/2-Update.ps1 @@ -12,6 +12,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -20,7 +21,7 @@ Configuration Example Ensure = "Present"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AlexW"; # Updated Property + User = "AlexW@$Domain"; # Updated Property } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/3-Remove.ps1 index 27ba43c715..e1990e8efd 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRoleAssignment/3-Remove.ps1 @@ -12,6 +12,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -20,7 +21,7 @@ Configuration Example Ensure = "Absent"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AlexW"; # Updated Property + User = "AlexW@$Domain"; # Updated Property } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 index 437b7ee3f1..b2a10de484 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 @@ -18,15 +18,16 @@ Configuration Example { EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' + Identity = 'Integration' Comment = 'Mail for Contoso' - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential + DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 index d1d7bf88d2..6d09b042bc 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 @@ -18,15 +18,15 @@ Configuration Example EXOOutboundConnector 'ConfigureOutboundConnector' { Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $True - CloudServicesMailEnabled = $True + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False Comment = "Outbound connector to Contoso" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True - IsTransportRuleScoped = $True - RecipientDomains = "*.contoso.com" - RouteAllMessagesViaOnPremises = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False TlsDomain = "*.contoso.com" TlsSettings = "DomainValidation" UseMxRecord = $True diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/2-Update.ps1 index 9f20787d0a..503f87c410 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/2-Update.ps1 @@ -18,15 +18,15 @@ Configuration Example EXOOutboundConnector 'ConfigureOutboundConnector' { Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $True - CloudServicesMailEnabled = $True + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False Comment = "Outbound connector to Contoso" ConnectorSource = "Default" - ConnectorType = "OnPremises" - Enabled = $False # Updated Property - IsTransportRuleScoped = $True - RecipientDomains = "*.contoso.com" - RouteAllMessagesViaOnPremises = $True + ConnectorType = "Partner" + Enabled = $False # Updated Property + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False TlsDomain = "*.contoso.com" TlsSettings = "DomainValidation" UseMxRecord = $True diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 index 044d825ba0..a70e94d02c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 @@ -19,7 +19,6 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - AccountType = "OrganizationalAccount" Enabled = $True Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 index 29be55ca27..a38a41068b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 @@ -19,7 +19,6 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - AccountType = "OrganizationalAccount" Enabled = $False # Updated Property Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-Create.ps1 index a520894b77..48d306104b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/1-Create.ps1 @@ -20,12 +20,12 @@ Configuration Example EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; - Capacity = 15; #Drift + Capacity = 15; City = ""; Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Present' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; IsWheelChairAccessible = $True; MTREnabled = $False; ParentType = "None"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/2-Update.ps1 index 0652a062c7..b84d5cc320 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/2-Update.ps1 @@ -25,7 +25,7 @@ Configuration Example Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Present' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; IsWheelChairAccessible = $True; MTREnabled = $False; ParentType = "None"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/3-Remove.ps1 index 9be622e644..51ad933226 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPlace/3-Remove.ps1 @@ -23,7 +23,7 @@ Configuration Example Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Absent' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 index 2bc4e0aee5..a3887a84fa 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 @@ -29,7 +29,7 @@ Configuration Example IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 index beeaa531a9..4aace58ca5 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 @@ -27,7 +27,7 @@ Configuration Example DisplaySenderName = $True DomainName = "*" IsInternal = $False - LineWrapSize = "Unlimited" + LineWrapSize = "Integration" MeetingForwardNotificationEnabled = $False Name = "Default" NonMimeCharacterSet = "iso-8859-1" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 index b10f42c4aa..feab8da8eb 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 @@ -20,9 +20,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 index 7b064d7d99..419c6f7d0d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 @@ -20,9 +20,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 index c94452d712..93694876a8 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 @@ -20,9 +20,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 index 6a672a2158..a01e4f058d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 @@ -20,9 +20,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/1-Create.ps1 index b672e18961..83fac8d5ff 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/1-Create.ps1 @@ -17,9 +17,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain") + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain") + Alias = "IntegrationSM" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/2-Update.ps1 index a009e6f9bc..addaba121b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/2-Update.ps1 @@ -17,9 +17,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain", "AlexW@$Domain") # Updated Property + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain", "IntegrationSM2@$Domain") + Alias = "IntegrationSM" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/3-Remove.ps1 index 3b1b6ce72b..90388f70c4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSharedMailbox/3-Remove.ps1 @@ -17,9 +17,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain", "AlexW@$Domain") # Updated Property + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain", "IntegrationSM2@$Domain") + Alias = "IntegrationSM" Ensure = "Absent" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 index 4d6573cdd3..4b79f0fa53 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 @@ -17,10 +17,10 @@ Configuration Example { EXOTransportRule 'ConfigureTransportRule' { - Name = "Ethical Wall - Sales and Brokerage Departments" - BetweenMemberOf1 = "Sales Department" - BetweenMemberOf2 = "Brokerage Department" - ExceptIfFrom = "Tony Smith","Pilar Ackerman" + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "Sales Team" + BetweenMemberOf2 = "Executives" + ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." Enabled = $True diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 index 39e2e3a262..8ef3a7d5ae 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 @@ -17,13 +17,13 @@ Configuration Example { EXOTransportRule 'ConfigureTransportRule' { - Name = "Ethical Wall - Sales and Brokerage Departments" - BetweenMemberOf1 = "Sales Department" - BetweenMemberOf2 = "Brokerage Department" - ExceptIfFrom = "Tony Smith","Pilar Ackerman" + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "Sales Team" + BetweenMemberOf2 = "Executives" + ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" - RejectMessageReasonText = "Updated" # Updated Property - Enabled = $True + RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." + Enabled = $False # Updated Property Ensure = "Present" Credential = $Credscredential } From 3d2e1cc3cf6d4c28bf749aebefff3882fc88ae9f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sun, 28 Jan 2024 18:42:09 +0000 Subject: [PATCH 024/171] Updated Resources and Cmdlet documentation pages --- .../EXOAuthenticationPolicyAssignment.md | 8 ++- .../exchange/EXODataEncryptionPolicy.md | 60 ------------------- .../exchange/EXODistributionGroup.md | 4 +- .../exchange/EXODkimSigningConfig.md | 9 ++- .../exchange/EXOGlobalAddressList.md | 1 + .../exchange/EXOHostedContentFilterPolicy.md | 4 +- .../exchange/EXOHostedContentFilterRule.md | 12 ++-- .../EXOHostedOutboundSpamFilterRule.md | 9 ++- .../resources/exchange/EXOInboundConnector.md | 20 +++---- .../docs/resources/exchange/EXOMailContact.md | 6 +- .../exchange/EXOManagementRoleAssignment.md | 9 ++- .../exchange/EXOOnPremisesOrganization.md | 13 ++-- .../exchange/EXOOutboundConnector.md | 26 ++++---- .../exchange/EXOPartnerApplication.md | 2 - docs/docs/resources/exchange/EXOPlace.md | 8 +-- .../resources/exchange/EXORemoteDomain.md | 4 +- .../exchange/EXOSafeAttachmentRule.md | 8 +-- .../resources/exchange/EXOSafeLinksRule.md | 8 +-- .../resources/exchange/EXOSharedMailbox.md | 21 ++++--- .../resources/exchange/EXOTransportRule.md | 20 +++---- 20 files changed, 104 insertions(+), 148 deletions(-) diff --git a/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md b/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md index 96b4ec6b82..498c4d50bf 100644 --- a/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md +++ b/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md @@ -48,11 +48,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Block Basic Auth" Ensure = "Present" Credential = $Credscredential @@ -79,7 +80,7 @@ Configuration Example { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Test Policy" # Updaqted Property Ensure = "Present" Credential = $Credscredential @@ -101,11 +102,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Test Policy" Ensure = "Absent" Credential = $Credscredential diff --git a/docs/docs/resources/exchange/EXODataEncryptionPolicy.md b/docs/docs/resources/exchange/EXODataEncryptionPolicy.md index 623f2893c4..50e4fe308e 100644 --- a/docs/docs/resources/exchange/EXODataEncryptionPolicy.md +++ b/docs/docs/resources/exchange/EXODataEncryptionPolicy.md @@ -45,66 +45,6 @@ To authenticate with Microsoft Exchange, this resource required the following pe This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. -```powershell -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXODataEncryptionPolicy 'ConfigureDataEncryptionPolicy' - { - Identity = 'US Mailboxes' - Name = 'All US Mailboxes' - Description = 'All Mailboxes of users in the US' - Enabled = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} -``` - -### Example 2 - -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. - -```powershell -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXODataEncryptionPolicy 'ConfigureDataEncryptionPolicy' - { - Identity = 'US Mailboxes' - Name = 'All US Mailboxes' - Description = 'All Mailboxes of users in the US. Updated' # Updated Property - Enabled = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} -``` - -### Example 3 - -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. - ```powershell Configuration Example { diff --git a/docs/docs/resources/exchange/EXODistributionGroup.md b/docs/docs/resources/exchange/EXODistributionGroup.md index d690f1b53f..cef3fac485 100644 --- a/docs/docs/resources/exchange/EXODistributionGroup.md +++ b/docs/docs/resources/exchange/EXODistributionGroup.md @@ -110,7 +110,7 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain"; + OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; @@ -154,7 +154,7 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain"; + OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/docs/docs/resources/exchange/EXODkimSigningConfig.md b/docs/docs/resources/exchange/EXODkimSigningConfig.md index c4811b04ff..42bb473064 100644 --- a/docs/docs/resources/exchange/EXODkimSigningConfig.md +++ b/docs/docs/resources/exchange/EXODkimSigningConfig.md @@ -55,12 +55,13 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { KeySize = 1024 - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain HeaderCanonicalization = "Relaxed" Enabled = $True BodyCanonicalization = "Relaxed" @@ -87,12 +88,13 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { KeySize = 1024 - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain HeaderCanonicalization = "Relaxed" Enabled = $False # Updated Property BodyCanonicalization = "Relaxed" @@ -119,11 +121,12 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXODkimSigningConfig 'ConfigureDKIMSigning' { - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain Ensure = "Absent" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOGlobalAddressList.md b/docs/docs/resources/exchange/EXOGlobalAddressList.md index e414e0b0cb..3f0066ea00 100644 --- a/docs/docs/resources/exchange/EXOGlobalAddressList.md +++ b/docs/docs/resources/exchange/EXOGlobalAddressList.md @@ -78,6 +78,7 @@ Configuration Example ConditionalCompany = "Contoso" ConditionalDepartment = "Human Resources" ConditionalStateOrProvince = "Washington" + IncludedRecipients = 'AllRecipients' Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md b/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md index 7bbe7e47f3..97cab0bb12 100644 --- a/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md +++ b/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md @@ -125,7 +125,7 @@ Configuration Example IncreaseScoreWithRedirectToOtherPort = "Off" InlineSafetyTipsEnabled = $True LanguageBlockList = @() - MakeDefault = $True + MakeDefault = $False MarkAsSpamBulkMail = "On" MarkAsSpamEmbedTagsInHtml = "Off" MarkAsSpamEmptyMessages = "Off" @@ -194,7 +194,7 @@ Configuration Example IncreaseScoreWithRedirectToOtherPort = "Off" InlineSafetyTipsEnabled = $True LanguageBlockList = @() - MakeDefault = $True + MakeDefault = $False MarkAsSpamBulkMail = "On" MarkAsSpamEmbedTagsInHtml = "Off" MarkAsSpamEmptyMessages = "Off" diff --git a/docs/docs/resources/exchange/EXOHostedContentFilterRule.md b/docs/docs/resources/exchange/EXOHostedContentFilterRule.md index 132f2f6de7..f208dc3fb1 100644 --- a/docs/docs/resources/exchange/EXOHostedContentFilterRule.md +++ b/docs/docs/resources/exchange/EXOHostedContentFilterRule.md @@ -65,10 +65,11 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Contoso Human Resources" + ExceptIfSentToMemberOf = "Legal Team" + RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" Credential = $Credscredential @@ -97,10 +98,11 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Contoso Human Resources" + ExceptIfSentToMemberOf = "Legal Team" + RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" Credential = $Credscredential @@ -129,7 +131,7 @@ Configuration Example { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" HostedContentFilterPolicy = "Integration CFP" Ensure = "Absent" Credential = $Credscredential diff --git a/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md b/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md index 1bd032a9a1..d24c221638 100644 --- a/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md +++ b/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md @@ -61,6 +61,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' @@ -68,7 +69,8 @@ Configuration Example Identity = "Contoso Executives" Comments = "Does not apply to Executives" Enabled = $True - ExceptIfFrom = "John Smith" + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = 'Executives' HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential @@ -93,6 +95,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' @@ -100,7 +103,8 @@ Configuration Example Identity = "Contoso Executives" Comments = "Does not apply to Executives" Enabled = $False # Updated Property - ExceptIfFrom = "John Smith" + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = 'Executives' HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential @@ -125,6 +129,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' diff --git a/docs/docs/resources/exchange/EXOInboundConnector.md b/docs/docs/resources/exchange/EXOInboundConnector.md index 1bc2741078..e8436e812a 100644 --- a/docs/docs/resources/exchange/EXOInboundConnector.md +++ b/docs/docs/resources/exchange/EXOInboundConnector.md @@ -70,16 +70,15 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" - CloudServicesMailEnabled = $True - Comment = "Inbound connector for Contoso" + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True RequireTls = $True SenderDomains = "*.contoso.com" TlsSenderCertificateName = "contoso.com" - TreatMessagesAsInternal = $True Ensure = "Present" Credential = $Credscredential } @@ -107,16 +106,15 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" - CloudServicesMailEnabled = $True - Comment = "Inbound connector for Contoso" + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $False # Updated Property RequireTls = $True SenderDomains = "*.contoso.com" TlsSenderCertificateName = "contoso.com" - TreatMessagesAsInternal = $True Ensure = "Present" Credential = $Credscredential } @@ -144,7 +142,7 @@ Configuration Example { EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" + Identity = "Integration Inbound Connector" Ensure = "Absent" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOMailContact.md b/docs/docs/resources/exchange/EXOMailContact.md index 063608382f..923a2d051c 100644 --- a/docs/docs/resources/exchange/EXOMailContact.md +++ b/docs/docs/resources/exchange/EXOMailContact.md @@ -101,7 +101,7 @@ Configuration Example ModeratedBy = @() ModerationEnabled = $false Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $true CustomAttribute1 = 'Custom Value 1' @@ -142,7 +142,7 @@ Configuration Example ModeratedBy = @() ModerationEnabled = $false Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $false # Updated Property CustomAttribute1 = 'Custom Value 1' @@ -178,7 +178,7 @@ Configuration Example Ensure = 'Absent' ExternalEmailAddress = 'SMTP:test@tailspintoys.com' Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $false # Updated Property CustomAttribute1 = 'Custom Value 1' diff --git a/docs/docs/resources/exchange/EXOManagementRoleAssignment.md b/docs/docs/resources/exchange/EXOManagementRoleAssignment.md index d9ee8fa96c..2ea3b0bb4a 100644 --- a/docs/docs/resources/exchange/EXOManagementRoleAssignment.md +++ b/docs/docs/resources/exchange/EXOManagementRoleAssignment.md @@ -60,6 +60,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -68,7 +69,7 @@ Configuration Example Ensure = "Present"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AdeleV"; + User = "AdeleV@$Domain"; } } } @@ -89,6 +90,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -97,7 +99,7 @@ Configuration Example Ensure = "Present"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AlexW"; # Updated Property + User = "AlexW@$Domain"; # Updated Property } } } @@ -118,6 +120,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRoleAssignment 'AssignManagementRole' @@ -126,7 +129,7 @@ Configuration Example Ensure = "Absent"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AlexW"; # Updated Property + User = "AlexW@$Domain"; # Updated Property } } } diff --git a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md index 9ad83d1e9d..29b28a9cd3 100644 --- a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md +++ b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md @@ -62,15 +62,16 @@ Configuration Example { EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' + Identity = 'Integration' Comment = 'Mail for Contoso' - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential + DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" } } } diff --git a/docs/docs/resources/exchange/EXOOutboundConnector.md b/docs/docs/resources/exchange/EXOOutboundConnector.md index 6f0d1388fe..071fbfda58 100644 --- a/docs/docs/resources/exchange/EXOOutboundConnector.md +++ b/docs/docs/resources/exchange/EXOOutboundConnector.md @@ -71,15 +71,15 @@ Configuration Example EXOOutboundConnector 'ConfigureOutboundConnector' { Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $True - CloudServicesMailEnabled = $True + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False Comment = "Outbound connector to Contoso" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True - IsTransportRuleScoped = $True - RecipientDomains = "*.contoso.com" - RouteAllMessagesViaOnPremises = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False TlsDomain = "*.contoso.com" TlsSettings = "DomainValidation" UseMxRecord = $True @@ -111,15 +111,15 @@ Configuration Example EXOOutboundConnector 'ConfigureOutboundConnector' { Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $True - CloudServicesMailEnabled = $True + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False Comment = "Outbound connector to Contoso" ConnectorSource = "Default" - ConnectorType = "OnPremises" - Enabled = $False # Updated Property - IsTransportRuleScoped = $True - RecipientDomains = "*.contoso.com" - RouteAllMessagesViaOnPremises = $True + ConnectorType = "Partner" + Enabled = $False # Updated Property + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False TlsDomain = "*.contoso.com" TlsSettings = "DomainValidation" UseMxRecord = $True diff --git a/docs/docs/resources/exchange/EXOPartnerApplication.md b/docs/docs/resources/exchange/EXOPartnerApplication.md index 3370ee3f64..e7830f4f35 100644 --- a/docs/docs/resources/exchange/EXOPartnerApplication.md +++ b/docs/docs/resources/exchange/EXOPartnerApplication.md @@ -61,7 +61,6 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - AccountType = "OrganizationalAccount" Enabled = $True Ensure = "Present" Credential = $Credscredential @@ -92,7 +91,6 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - AccountType = "OrganizationalAccount" Enabled = $False # Updated Property Ensure = "Present" Credential = $Credscredential diff --git a/docs/docs/resources/exchange/EXOPlace.md b/docs/docs/resources/exchange/EXOPlace.md index 13d3b4eba4..23742979fc 100644 --- a/docs/docs/resources/exchange/EXOPlace.md +++ b/docs/docs/resources/exchange/EXOPlace.md @@ -78,12 +78,12 @@ Configuration Example EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; - Capacity = 15; #Drift + Capacity = 15; City = ""; Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Present' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; IsWheelChairAccessible = $True; MTREnabled = $False; ParentType = "None"; @@ -123,7 +123,7 @@ Configuration Example Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Present' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; IsWheelChairAccessible = $True; MTREnabled = $False; ParentType = "None"; @@ -161,7 +161,7 @@ Configuration Example Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Absent' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; } } } diff --git a/docs/docs/resources/exchange/EXORemoteDomain.md b/docs/docs/resources/exchange/EXORemoteDomain.md index d8f1373597..f81c377297 100644 --- a/docs/docs/resources/exchange/EXORemoteDomain.md +++ b/docs/docs/resources/exchange/EXORemoteDomain.md @@ -88,7 +88,7 @@ Configuration Example IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False @@ -132,7 +132,7 @@ Configuration Example DisplaySenderName = $True DomainName = "*" IsInternal = $False - LineWrapSize = "Unlimited" + LineWrapSize = "Integration" MeetingForwardNotificationEnabled = $False Name = "Default" NonMimeCharacterSet = "iso-8859-1" diff --git a/docs/docs/resources/exchange/EXOSafeAttachmentRule.md b/docs/docs/resources/exchange/EXOSafeAttachmentRule.md index 9e4b1e9a27..d7dbef3929 100644 --- a/docs/docs/resources/exchange/EXOSafeAttachmentRule.md +++ b/docs/docs/resources/exchange/EXOSafeAttachmentRule.md @@ -67,9 +67,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } @@ -100,9 +100,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOSafeLinksRule.md b/docs/docs/resources/exchange/EXOSafeLinksRule.md index 7f6a684f88..e83e251fc2 100644 --- a/docs/docs/resources/exchange/EXOSafeLinksRule.md +++ b/docs/docs/resources/exchange/EXOSafeLinksRule.md @@ -67,9 +67,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } @@ -100,9 +100,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOSharedMailbox.md b/docs/docs/resources/exchange/EXOSharedMailbox.md index 75901ef81e..ff1c50ddc9 100644 --- a/docs/docs/resources/exchange/EXOSharedMailbox.md +++ b/docs/docs/resources/exchange/EXOSharedMailbox.md @@ -57,9 +57,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain") + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain") + Alias = "IntegrationSM" Ensure = "Present" Credential = $Credscredential } @@ -87,9 +88,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain", "AlexW@$Domain") # Updated Property + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain", "IntegrationSM2@$Domain") + Alias = "IntegrationSM" Ensure = "Present" Credential = $Credscredential } @@ -117,9 +119,10 @@ Configuration Example { EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain", "AlexW@$Domain") # Updated Property + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain", "IntegrationSM2@$Domain") + Alias = "IntegrationSM" Ensure = "Absent" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOTransportRule.md b/docs/docs/resources/exchange/EXOTransportRule.md index ddba9efe92..6908c2b82d 100644 --- a/docs/docs/resources/exchange/EXOTransportRule.md +++ b/docs/docs/resources/exchange/EXOTransportRule.md @@ -221,10 +221,10 @@ Configuration Example { EXOTransportRule 'ConfigureTransportRule' { - Name = "Ethical Wall - Sales and Brokerage Departments" - BetweenMemberOf1 = "Sales Department" - BetweenMemberOf2 = "Brokerage Department" - ExceptIfFrom = "Tony Smith","Pilar Ackerman" + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "Sales Team" + BetweenMemberOf2 = "Executives" + ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." Enabled = $True @@ -255,13 +255,13 @@ Configuration Example { EXOTransportRule 'ConfigureTransportRule' { - Name = "Ethical Wall - Sales and Brokerage Departments" - BetweenMemberOf1 = "Sales Department" - BetweenMemberOf2 = "Brokerage Department" - ExceptIfFrom = "Tony Smith","Pilar Ackerman" + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "Sales Team" + BetweenMemberOf2 = "Executives" + ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" - RejectMessageReasonText = "Updated" # Updated Property - Enabled = $True + RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." + Enabled = $False # Updated Property Ensure = "Present" Credential = $Credscredential } From 6c61af48ed9bf0ab11a8743a992e6a0e4e7c3d60 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sun, 28 Jan 2024 18:43:58 +0000 Subject: [PATCH 025/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 94 +++++++++---------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 56c0957ebf..f043cec0e0 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -125,7 +125,7 @@ } EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { - UserName = "AdeleV" + UserName = "AdeleV@$Domain" AuthenticationPolicyName = "Block Basic Auth" Ensure = "Present" Credential = $Credscredential @@ -163,15 +163,6 @@ Ensure = "Present" Credential = $Credscredential } - EXODataEncryptionPolicy 'ConfigureDataEncryptionPolicy' - { - Identity = 'US Mailboxes' - Name = 'All US Mailboxes' - Description = 'All Mailboxes of users in the US' - Enabled = $true - Ensure = "Present" - Credential = $Credscredential - } EXODistributionGroup 'DemoDG' { Alias = "demodg"; @@ -187,7 +178,7 @@ ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain"; + OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; @@ -196,7 +187,7 @@ EXODkimSigningConfig 'ConfigureDKIMSigning' { KeySize = 1024 - Identity = 'contoso.onmicrosoft.com' + Identity = $Domain HeaderCanonicalization = "Relaxed" Enabled = $True BodyCanonicalization = "Relaxed" @@ -220,6 +211,7 @@ ConditionalCompany = "Contoso" ConditionalDepartment = "Human Resources" ConditionalStateOrProvince = "Washington" + IncludedRecipients = 'AllRecipients' Ensure = "Present" Credential = $Credscredential } @@ -256,7 +248,7 @@ IncreaseScoreWithRedirectToOtherPort = "Off" InlineSafetyTipsEnabled = $True LanguageBlockList = @() - MakeDefault = $True + MakeDefault = $False MarkAsSpamBulkMail = "On" MarkAsSpamEmbedTagsInHtml = "Off" MarkAsSpamEmptyMessages = "Off" @@ -284,10 +276,11 @@ } EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' { - Identity = "Contoso Recipients" + Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Contoso Human Resources" + ExceptIfSentToMemberOf = "Legal Team" + RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" Credential = $Credscredential @@ -313,23 +306,23 @@ Identity = "Contoso Executives" Comments = "Does not apply to Executives" Enabled = $True - ExceptIfFrom = "John Smith" + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = 'Executives' HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential } EXOInboundConnector 'ConfigureInboundConnector' { - Identity = "Contoso Inbound Connector" - CloudServicesMailEnabled = $True - Comment = "Inbound connector for Contoso" + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True RequireTls = $True SenderDomains = "*.contoso.com" TlsSenderCertificateName = "contoso.com" - TreatMessagesAsInternal = $True Ensure = "Present" Credential = $Credscredential } @@ -364,7 +357,7 @@ ModeratedBy = @() ModerationEnabled = $false Name = 'My Test Contact' - OrganizationalUnit = "nampr03a010.prod.outlook.com/Microsoft Exchange Hosted Organizations/$Domain" + OrganizationalUnit = $Domain SendModerationNotifications = 'Always' UsePreferMessageFormat = $true CustomAttribute1 = 'Custom Value 1' @@ -419,7 +412,7 @@ Ensure = "Present"; Name = "MyManagementRoleAssignment"; Role = "UserApplication"; - User = "AdeleV"; + User = "AdeleV@$Domain"; } EXOMessageClassification 'ConfigureMessageClassification' { @@ -519,15 +512,16 @@ } EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' + Identity = 'Integration' Comment = 'Mail for Contoso' - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential + DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" } EXOOrganizationRelationship 'ConfigureOrganizationRelationship' { @@ -550,15 +544,15 @@ EXOOutboundConnector 'ConfigureOutboundConnector' { Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $True - CloudServicesMailEnabled = $True + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False Comment = "Outbound connector to Contoso" ConnectorSource = "Default" - ConnectorType = "OnPremises" + ConnectorType = "Partner" Enabled = $True - IsTransportRuleScoped = $True - RecipientDomains = "*.contoso.com" - RouteAllMessagesViaOnPremises = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False TlsDomain = "*.contoso.com" TlsSettings = "DomainValidation" UseMxRecord = $True @@ -647,7 +641,6 @@ { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - AccountType = "OrganizationalAccount" Enabled = $True Ensure = "Present" Credential = $Credscredential @@ -655,12 +648,12 @@ EXOPlace 'TestPlace' { AudioDeviceName = "MyAudioDevice"; - Capacity = 15; #Drift + Capacity = 15; City = ""; Credential = $Credscredential DisplayDeviceName = "DisplayDeviceName"; Ensure = 'Present' - Identity = "MyRoom@$Domain"; + Identity = "Hood@$Domain"; IsWheelChairAccessible = $True; MTREnabled = $False; ParentType = "None"; @@ -698,7 +691,7 @@ IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False @@ -740,9 +733,9 @@ Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } @@ -764,17 +757,18 @@ Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Research Department Managers" + ExceptIfSentToMemberOf = "Executives" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Research Department" + SentToMemberOf = "Legal Team" Ensure = "Present" Credential = $Credscredential } EXOSharedMailbox 'SharedMailbox' { - DisplayName = "Test" - PrimarySMTPAddress = "Test@$Domain" - EmailAddresses = @("AdeleV@$Domain") + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain") + Alias = "IntegrationSM" Ensure = "Present" Credential = $Credscredential } @@ -789,10 +783,10 @@ } EXOTransportRule 'ConfigureTransportRule' { - Name = "Ethical Wall - Sales and Brokerage Departments" - BetweenMemberOf1 = "Sales Department" - BetweenMemberOf2 = "Brokerage Department" - ExceptIfFrom = "Tony Smith","Pilar Ackerman" + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "Sales Team" + BetweenMemberOf2 = "Executives" + ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." Enabled = $True From d0e2e5195e105c920e7c0aeb39c41060fa957256 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 08:08:19 -0500 Subject: [PATCH 026/171] Updated Integration Tests for EXO --- CHANGELOG.md | 2 ++ .../MSFT_EXOHostedConnectionFilterPolicy.psm1 | 21 +++++++------- .../MSFT_EXOHostedContentFilterRule.psm1 | 7 +++-- .../1-Create.ps1 | 29 ------------------- .../2-Update.ps1 | 4 +-- .../3-Remove.ps1 | 24 --------------- 6 files changed, 19 insertions(+), 68 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/1-Create.ps1 delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/3-Remove.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 153396122d..6a473553ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* EXOHostedContentFilterRule + * Changed logic to retrieve the Rules by name. Using the Policy's name instead. * TeamsEmergencyCallRoutingPolicy * Fix deletion of resource FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 index 4f98aaa8e9..16d19dad46 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 @@ -96,7 +96,7 @@ function Get-TargetResource try { - $HostedConnectionFilterPolicys = Get-HostedConnectionFilterPolicy -ErrorAction Stop + $HostedConnectionFilterPolicy = Get-HostedConnectionFilterPolicy -Identity $Identity -ErrorAction Stop } catch { @@ -107,10 +107,9 @@ function Get-TargetResource return $nullReturn } - $HostedConnectionFilterPolicy = $HostedConnectionFilterPolicys | Where-Object -FilterScript { $_. Identity -eq $Identity } if (-not $HostedConnectionFilterPolicy) { - Write-Verbose -Message "HostedConnectionFilterPolicy $($Identity) does not exist." + Write-Verbose -Message "HostedConnectionFilterPolicy [$($Identity)] does not exist." return $nullReturn } else @@ -234,9 +233,7 @@ function Set-TargetResource $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters - $HostedConnectionFilterPolicys = Get-HostedConnectionFilterPolicy - - $HostedConnectionFilterPolicy = $HostedConnectionFilterPolicys | Where-Object -FilterScript { $_.Identity -eq $Identity } + $CurrentInstance = Get-TargetResource @PSBoundParameters $HostedConnectionFilterPolicyParams = [System.Collections.Hashtable]($PSBoundParameters) $HostedConnectionFilterPolicyParams.Remove('Ensure') | Out-Null @@ -257,7 +254,7 @@ function Set-TargetResource $HostedConnectionFilterPolicyParams.Remove('RuleScope') | Out-Null } - if (('Present' -eq $Ensure ) -and ($null -eq $HostedConnectionFilterPolicy)) + if (('Present' -eq $Ensure ) -and $CurrentInstance.Ensure -eq 'Absent') { $HostedConnectionFilterPolicyParams += @{ Name = $HostedConnectionFilterPolicyParams.Identity @@ -265,14 +262,18 @@ function Set-TargetResource $HostedConnectionFilterPolicyParams.Remove('Identity') | Out-Null if ($PSBoundParameters.MakeDefault) { + Write-Verbose -Message "Creating New Default Policy {$Identity}" New-HostedConnectionFilterPolicy @HostedConnectionFilterPolicyParams -MakeDefault } else { + Write-Verbose -Message "Creating New Policy {$Identity}" New-HostedConnectionFilterPolicy @HostedConnectionFilterPolicyParams } + + Write-Verbose -Message "With Parameters: $(Convert-M365DscHashtableToString -Hashtable $HostedConnectionFilterPolicyParams)" } - elseif (('Present' -eq $Ensure ) -and ($HostedConnectionFilterPolicy)) + elseif (('Present' -eq $Ensure ) -and $CurrentInstance.Ensure -eq 'Present') { if ($PSBoundParameters.MakeDefault) { @@ -283,9 +284,9 @@ function Set-TargetResource Set-HostedConnectionFilterPolicy @HostedConnectionFilterPolicyParams -Confirm:$false } } - elseif (('Absent' -eq $Ensure ) -and ($HostedConnectionFilterPolicy)) + elseif (('Absent' -eq $Ensure ) -and $CurrentInstance.Ensure -'Present') { - Write-Verbose -Message "Removing HostedConnectionFilterPolicy $($Identity) " + Write-Verbose -Message "Removing HostedConnectionFilterPolicy $($Identity)" Remove-HostedConnectionFilterPolicy -Identity $Identity -Confirm:$false } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterRule/MSFT_EXOHostedContentFilterRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterRule/MSFT_EXOHostedContentFilterRule.psm1 index 7e8fc2eea6..ff9a042c4b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterRule/MSFT_EXOHostedContentFilterRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterRule/MSFT_EXOHostedContentFilterRule.psm1 @@ -114,7 +114,7 @@ function Get-TargetResource { try { - $HostedContentFilterRules = Get-HostedContentFilterRule -ErrorAction Stop + $HostedContentFilterRule = Get-HostedContentFilterRule -Identity $HostedContentFilterPolicy -ErrorAction Stop } catch { @@ -123,8 +123,6 @@ function Get-TargetResource -Exception $_ ` -Source $MyInvocation.MyCommand.ModuleName } - - $HostedContentFilterRule = $HostedContentFilterRules | Where-Object -FilterScript { $_.Identity -eq $Identity } if (-not $HostedContentFilterRule) { Write-Verbose -Message "HostedContentFilterRule $($Identity) does not exist." @@ -316,6 +314,7 @@ function Set-TargetResource Remove-HostedContentFilterRule -Identity $Identity -Confirm:$false } Write-Verbose -Message "Creating new HostedContentFilterRule {$Identity}" + Write-Verbose -Message "With Parameters: $(Convert-M365DscHashtableToString -Hashtable $CreationParams)" $CreationParams.Add('Name', $Identity) $CreationParams.Remove('Identity') | Out-Null New-HostedContentFilterRule @CreationParams @@ -332,6 +331,7 @@ function Set-TargetResource $UpdateParams.Remove('CertificatePassword') | Out-Null $UpdateParams.Remove('ManagedIdentity') | Out-Null $UpdateParams.Remove('Enabled') | Out-Null + $UpdateParams.Identity = $HostedContentFilterPolicy if ($CurrentValues.HostedContentFilterPolicy -eq $UpdateParams.HostedContentFilterPolicy ) { $UpdateParams.Remove('HostedContentFilterPolicy') | Out-Null @@ -456,6 +456,7 @@ function Test-TargetResource $ValuesToCheck.Remove('CertificatePath') | Out-Null $ValuesToCheck.Remove('CertificatePassword') | Out-Null $ValuesToCheck.Remove('ManagedIdentity') | Out-Null + $ValuesToCheck.Remove('Identity') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/1-Create.ps1 deleted file mode 100644 index dc5cfd26cb..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/1-Create.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -<# -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(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' - { - Identity = "Integration Policy" - AdminDisplayName = "" - EnableSafeList = $False - IPAllowList = @() - IPBlockList = @() - MakeDefault = $False - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/2-Update.ps1 index 5f06631889..dbad190990 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/2-Update.ps1 @@ -16,12 +16,12 @@ Configuration Example { EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' { - Identity = "Integration Policy" + Identity = "Default" AdminDisplayName = "" EnableSafeList = $True # Updated Property IPAllowList = @() IPBlockList = @() - MakeDefault = $False + MakeDefault = $True Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/3-Remove.ps1 deleted file mode 100644 index dcba8d2b18..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedConnectionFilterPolicy/3-Remove.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -<# -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(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' - { - Identity = "Integration Policy" - Ensure = "Absent" - Credential = $Credscredential - } - } -} From 4475a348e4fd70f44db54509662cbd7b4616db5f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 08:23:45 -0500 Subject: [PATCH 027/171] Update 1-Create.ps1 --- .../EXOOnPremisesOrganization/1-Create.ps1 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 index b2a10de484..0edc27eaba 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 @@ -29,5 +29,23 @@ Configuration Example Credential = $Credscredential DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" } + EXOOutboundConnector 'ConfigureOutboundConnector' + { + Identity = "Contoso Outbound Connector" + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False + Comment = "Outbound connector to Contoso" + ConnectorSource = "Default" + ConnectorType = "Partner" + Enabled = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False + TlsDomain = "*.contoso.com" + TlsSettings = "DomainValidation" + UseMxRecord = $True + Ensure = "Present" + Credential = $Credscredential + } } } From 8f052788caa8d6fadd471e3842956ed0d03c4ef1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 08:24:19 -0500 Subject: [PATCH 028/171] Update 1-Create.ps1 --- .../Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 index 0edc27eaba..98ed5fd428 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/1-Create.ps1 @@ -27,9 +27,9 @@ Configuration Example OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential - DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" + DependsOn = "[EXOOutboundConnector]OutboundDependency" } - EXOOutboundConnector 'ConfigureOutboundConnector' + EXOOutboundConnector 'OutboundDependency' { Identity = "Contoso Outbound Connector" AllAcceptedDomains = $False From 3986ef8ea07a58cd79323fd0b76e453fa3119b4c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 09:09:41 -0500 Subject: [PATCH 029/171] Fixes --- .../MSFT_EXOHostedConnectionFilterPolicy.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 index 16d19dad46..901a6c1282 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedConnectionFilterPolicy/MSFT_EXOHostedConnectionFilterPolicy.psm1 @@ -284,7 +284,7 @@ function Set-TargetResource Set-HostedConnectionFilterPolicy @HostedConnectionFilterPolicyParams -Confirm:$false } } - elseif (('Absent' -eq $Ensure ) -and $CurrentInstance.Ensure -'Present') + elseif (('Absent' -eq $Ensure ) -and $CurrentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Removing HostedConnectionFilterPolicy $($Identity)" Remove-HostedConnectionFilterPolicy -Identity $Identity -Confirm:$false From a5011174deb8875e425f46fc1319858198211bb7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 14:23:09 +0000 Subject: [PATCH 030/171] Updated Resources and Cmdlet documentation pages --- .../EXOHostedConnectionFilterPolicy.md | 63 +------------------ .../exchange/EXOOnPremisesOrganization.md | 20 +++++- 2 files changed, 21 insertions(+), 62 deletions(-) diff --git a/docs/docs/resources/exchange/EXOHostedConnectionFilterPolicy.md b/docs/docs/resources/exchange/EXOHostedConnectionFilterPolicy.md index 448373b0b7..80fc3a0d28 100644 --- a/docs/docs/resources/exchange/EXOHostedConnectionFilterPolicy.md +++ b/docs/docs/resources/exchange/EXOHostedConnectionFilterPolicy.md @@ -59,44 +59,12 @@ Configuration Example { EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' { - Identity = "Integration Policy" - AdminDisplayName = "" - EnableSafeList = $False - IPAllowList = @() - IPBlockList = @() - MakeDefault = $False - Ensure = "Present" - Credential = $Credscredential - } - } -} -``` - -### Example 2 - -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. - -```powershell -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' - { - Identity = "Integration Policy" + Identity = "Default" AdminDisplayName = "" EnableSafeList = $True # Updated Property IPAllowList = @() IPBlockList = @() - MakeDefault = $False + MakeDefault = $True Ensure = "Present" Credential = $Credscredential } @@ -104,30 +72,3 @@ Configuration Example } ``` -### Example 3 - -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. - -```powershell -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' - { - Identity = "Integration Policy" - Ensure = "Absent" - Credential = $Credscredential - } - } -} -``` - diff --git a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md index 29b28a9cd3..9a5dcd5078 100644 --- a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md +++ b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md @@ -71,7 +71,25 @@ Configuration Example OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential - DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" + DependsOn = "[EXOOutboundConnector]OutboundDependency" + } + EXOOutboundConnector 'OutboundDependency' + { + Identity = "Contoso Outbound Connector" + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False + Comment = "Outbound connector to Contoso" + ConnectorSource = "Default" + ConnectorType = "Partner" + Enabled = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False + TlsDomain = "*.contoso.com" + TlsSettings = "DomainValidation" + UseMxRecord = $True + Ensure = "Present" + Credential = $Credscredential } } } From 2d26dc14d8c4f2e11a16fc83bd5852d4e6e4d269 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 14:25:16 +0000 Subject: [PATCH 031/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index f043cec0e0..69340ee68f 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -215,17 +215,6 @@ Ensure = "Present" Credential = $Credscredential } - EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' - { - Identity = "Integration Policy" - AdminDisplayName = "" - EnableSafeList = $False - IPAllowList = @() - IPBlockList = @() - MakeDefault = $False - Ensure = "Present" - Credential = $Credscredential - } EXOHostedContentFilterPolicy 'ConfigureHostedContentFilterPolicy' { Identity = "Integration CFP" @@ -521,7 +510,25 @@ OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential - DependsOn = "[EXOOutboundConnector]ConfigureOutboundConnector" + DependsOn = "[EXOOutboundConnector]OutboundDependency" + } + EXOOutboundConnector 'OutboundDependency' + { + Identity = "Contoso Outbound Connector" + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False + Comment = "Outbound connector to Contoso" + ConnectorSource = "Default" + ConnectorType = "Partner" + Enabled = $True + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False + TlsDomain = "*.contoso.com" + TlsSettings = "DomainValidation" + UseMxRecord = $True + Ensure = "Present" + Credential = $Credscredential } EXOOrganizationRelationship 'ConfigureOrganizationRelationship' { From bc7f490917b0529df6f5ad46bbdf6db77e9d8072 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 12:44:12 -0500 Subject: [PATCH 032/171] Delete 1-Create.ps1 --- .../EXOOutboundConnector/1-Create.ps1 | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 deleted file mode 100644 index 6d09b042bc..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOutboundConnector/1-Create.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -<# -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(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOOutboundConnector 'ConfigureOutboundConnector' - { - Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $False - CloudServicesMailEnabled = $False - Comment = "Outbound connector to Contoso" - ConnectorSource = "Default" - ConnectorType = "Partner" - Enabled = $True - IsTransportRuleScoped = $False - RecipientDomains = "contoso.com" - RouteAllMessagesViaOnPremises = $False - TlsDomain = "*.contoso.com" - TlsSettings = "DomainValidation" - UseMxRecord = $True - Ensure = "Present" - Credential = $Credscredential - } - } -} From e95b11855f4feed1bf6cb1a782c1a4ef96bce7e0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 17:45:27 +0000 Subject: [PATCH 033/171] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOOutboundConnector.md | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/docs/docs/resources/exchange/EXOOutboundConnector.md b/docs/docs/resources/exchange/EXOOutboundConnector.md index 071fbfda58..ff0efa22cc 100644 --- a/docs/docs/resources/exchange/EXOOutboundConnector.md +++ b/docs/docs/resources/exchange/EXOOutboundConnector.md @@ -55,46 +55,6 @@ To authenticate with Microsoft Exchange, this resource required the following pe This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. -```powershell -Configuration Example -{ - param - ( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - node localhost - { - EXOOutboundConnector 'ConfigureOutboundConnector' - { - Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $False - CloudServicesMailEnabled = $False - Comment = "Outbound connector to Contoso" - ConnectorSource = "Default" - ConnectorType = "Partner" - Enabled = $True - IsTransportRuleScoped = $False - RecipientDomains = "contoso.com" - RouteAllMessagesViaOnPremises = $False - TlsDomain = "*.contoso.com" - TlsSettings = "DomainValidation" - UseMxRecord = $True - Ensure = "Present" - Credential = $Credscredential - } - } -} -``` - -### Example 2 - -This example is used to test new resources and showcase the usage of new resources being worked on. -It is not meant to use as a production baseline. - ```powershell Configuration Example { @@ -130,7 +90,7 @@ Configuration Example } ``` -### Example 3 +### Example 2 This example is used to test new resources and showcase the usage of new resources being worked on. It is not meant to use as a production baseline. From 15bbf320256bfe0e30d2249f9f689afccd17b163 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 17:47:25 +0000 Subject: [PATCH 034/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 69340ee68f..1df315f69b 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -548,24 +548,6 @@ Ensure = "Present" Credential = $Credscredential } - EXOOutboundConnector 'ConfigureOutboundConnector' - { - Identity = "Contoso Outbound Connector" - AllAcceptedDomains = $False - CloudServicesMailEnabled = $False - Comment = "Outbound connector to Contoso" - ConnectorSource = "Default" - ConnectorType = "Partner" - Enabled = $True - IsTransportRuleScoped = $False - RecipientDomains = "contoso.com" - RouteAllMessagesViaOnPremises = $False - TlsDomain = "*.contoso.com" - TlsSettings = "DomainValidation" - UseMxRecord = $True - Ensure = "Present" - Credential = $Credscredential - } EXOOwaMailboxPolicy 'ConfigureOwaMailboxPolicy' { Name = "OwaMailboxPolicy-Integration" From 827cc0df3f4719125c75e34064d8aee92c963a65 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 13:18:33 -0500 Subject: [PATCH 035/171] Fixes --- .../AADSecurityDefaults/{3-Remove.ps1 => 2-Update.ps1} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/{3-Remove.ps1 => 2-Update.ps1} (95%) diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/2-Update.ps1 similarity index 95% rename from Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/3-Remove.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/2-Update.ps1 index 3082922b75..8ed7979197 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADSecurityDefaults/2-Update.ps1 @@ -19,7 +19,7 @@ Configuration Example Credential = $Credscredential; Description = "Security defaults is a set of basic identity security mechanisms recommended by Microsoft. When enabled, these recommendations will be automatically enforced in your organization. Administrators and users will be better protected from common identity related attacks."; DisplayName = "Security Defaults"; - IsEnabled = $True; + IsEnabled = $False; IsSingleInstance = "Yes"; } } From b17f0d52a52d129688e32d0e7fa15740261105c5 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 18:20:01 +0000 Subject: [PATCH 036/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADSecurityDefaults.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/azure-ad/AADSecurityDefaults.md b/docs/docs/resources/azure-ad/AADSecurityDefaults.md index e7fd866152..ad0419bced 100644 --- a/docs/docs/resources/azure-ad/AADSecurityDefaults.md +++ b/docs/docs/resources/azure-ad/AADSecurityDefaults.md @@ -70,7 +70,7 @@ Configuration Example Credential = $Credscredential; Description = "Security defaults is a set of basic identity security mechanisms recommended by Microsoft. When enabled, these recommendations will be automatically enforced in your organization. Administrators and users will be better protected from common identity related attacks."; DisplayName = "Security Defaults"; - IsEnabled = $True; + IsEnabled = $False; IsSingleInstance = "Yes"; } } From 23723cdb43d8bd592da6d238b0e9f6bf09ba4616 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 18:25:01 +0000 Subject: [PATCH 037/171] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Update.Tests.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index a7e5141668..21be834009 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -695,6 +695,14 @@ Credential = $Credscredential Ensure = 'Present' } + AADSecurityDefaults 'Defaults' + { + Credential = $Credscredential; + Description = "Security defaults is a set of basic identity security mechanisms recommended by Microsoft. When enabled, these recommendations will be automatically enforced in your organization. Administrators and users will be better protected from common identity related attacks."; + DisplayName = "Security Defaults"; + IsEnabled = $False; + IsSingleInstance = "Yes"; + } AADServicePrincipal 'AADServicePrincipal' { AppId = 'AppDisplayName' From 73127d48d1a10029c8ad00be54857f30c77592cd Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 18:28:04 +0000 Subject: [PATCH 038/171] Updated {Update} AAD Integration Tests --- .../M365DSCIntegration.AAD.Remove.Tests.ps1 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 index 6415d0c12a..15a3838ebc 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Remove.Tests.ps1 @@ -199,14 +199,6 @@ } }; } - AADSecurityDefaults 'Defaults' - { - Credential = $Credscredential; - Description = "Security defaults is a set of basic identity security mechanisms recommended by Microsoft. When enabled, these recommendations will be automatically enforced in your organization. Administrators and users will be better protected from common identity related attacks."; - DisplayName = "Security Defaults"; - IsEnabled = $True; - IsSingleInstance = "Yes"; - } AADServicePrincipal 'AADServicePrincipal' { AppId = "AppDisplayName" From fabafadacaa9283a74e322ed1719df6c8a7e632e Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Tue, 30 Jan 2024 19:48:11 +0100 Subject: [PATCH 039/171] Fixed parameters and set default value for 'AccessRights' --- .../MSFT_EXORecipientPermission.psm1 | 28 +++++++++---------- .../MSFT_EXORecipientPermission.schema.mof | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 index 399d1f64ac..95b8ae0583 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 @@ -12,10 +12,10 @@ function Get-TargetResource [System.String] $Trustee, - [Parameter(Mandatory = $true)] + [Parameter()] [ValidateSet('SendAs')] [System.String[]] - $AccessRights, + $AccessRights = 'SendAs', [Parameter()] [ValidateSet('Present', 'Absent')] @@ -138,18 +138,18 @@ function Set-TargetResource [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Trustee, [Parameter()] [ValidateSet('SendAs')] - [System.String] - $AccessRights, + [System.String[]] + $AccessRights = 'SendAs', [Parameter()] [ValidateSet('Present', 'Absent')] @@ -248,18 +248,18 @@ function Test-TargetResource [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Trustee, [Parameter()] [ValidateSet('SendAs')] - [System.String] - $AccessRights, + [System.String[]] + $AccessRights = 'SendAs', [Parameter()] [ValidateSet('Present', 'Absent')] @@ -331,18 +331,18 @@ function Export-TargetResource [CmdletBinding()] param ( - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Identity, - [Parameter()] + [Parameter(Mandatory = $true)] [System.String] $Trustee, [Parameter()] [ValidateSet('SendAs')] - [System.String] - $AccessRights, + [System.String[]] + $AccessRights = 'SendAs', [Parameter()] [ValidateSet('Present', 'Absent')] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof index 4a12e9bdce..6efdab4c07 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.schema.mof @@ -3,7 +3,7 @@ class MSFT_EXORecipientPermission : OMI_BaseResource { [Key, Description("The mailbox the permission should be given on.")] String Identity; [Key, Description("The account to give the permission to.")] String Trustee; - [Write, Description("The access rights granted to the account. Only 'SendAs' is supported.")] String AccessRights; + [Write, Description("The access rights granted to the account. Only 'SendAs' is supported.")] String AccessRights[]; [Write, Description("Present ensures the group exists, absent ensures it is removed"), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Exchange Global Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; From c8499c9854b94c6b7bbc3ba86205f15a6d311a4d Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Tue, 30 Jan 2024 19:51:11 +0100 Subject: [PATCH 040/171] Fixed typo --- .../DSCResources/MSFT_EXORecipientPermission/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md index 054863a71a..611e51a3f4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/readme.md @@ -2,4 +2,4 @@ ## Description -This resource allows users to retrieve Office 365 Recipient Permission. +This resource allows users to retrieve Office 365 Recipient Permissions. From 44793e8d90540edbf467b203efa116aaeec60843 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 16:42:28 -0500 Subject: [PATCH 041/171] Various Fixes for EXO workload --- CHANGELOG.md | 16 ++++++++ .../MSFT_EXOAvailabilityAddressSpace.psm1 | 35 +++++++++++++++--- .../MSFT_EXOAvailabilityConfig.psm1 | 8 +++- .../MSFT_EXODistributionGroup.psm1 | 37 ++++++++++++++++++- .../MSFT_EXOHostedContentFilterPolicy.psm1 | 19 ++++++---- .../MSFT_EXOIntraOrganizationConnector.psm1 | 5 +++ .../MSFT_EXOMalwareFilterRule.psm1 | 7 +++- .../MSFT_EXOMessageClassification.psm1 | 3 +- .../MSFT_EXOOMEConfiguration.psm1 | 2 +- .../MSFT_EXOSafeLinksPolicy.psm1 | 11 ++---- .../EXOHostedContentFilterPolicy/1-Create.ps1 | 4 -- .../EXOHostedContentFilterPolicy/2-Update.ps1 | 4 -- .../EXOHostedContentFilterRule/1-Create.ps1 | 3 +- .../EXOHostedContentFilterRule/2-Update.ps1 | 3 +- .../1-Create.ps1 | 2 +- .../2-Update.ps1 | 2 +- .../Resources/EXOManagementRole/1-Create.ps1 | 3 +- .../Resources/EXOManagementRole/2-Update.ps1 | 3 +- .../EXOOfflineAddressBook/1-Create.ps1 | 2 +- .../EXOOfflineAddressBook/2-Update.ps1 | 2 +- .../Resources/EXORemoteDomain/1-Create.ps1 | 2 +- .../Resources/EXORemoteDomain/2-Update.ps1 | 2 +- .../EXOSafeAttachmentRule/1-Create.ps1 | 5 ++- .../EXOSafeAttachmentRule/2-Update.ps1 | 5 ++- .../Resources/EXOSafeLinksPolicy/1-Create.ps1 | 1 - .../Resources/EXOSafeLinksPolicy/2-Update.ps1 | 1 - .../Resources/EXOSafeLinksRule/1-Create.ps1 | 5 ++- .../Resources/EXOSafeLinksRule/2-Update.ps1 | 5 ++- .../Resources/EXOTransportRule/1-Create.ps1 | 5 ++- .../Resources/EXOTransportRule/2-Update.ps1 | 5 ++- 30 files changed, 147 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a473553ef..0072b6ac1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,24 @@ # UNRELEASED +* EXOAvailabilityAddressSpace + * Added support for the TargetServiceEpr and TargetTenantId parameters. + * Fixed the logic to retrieve existing instance by Forest Name. +* EXODistributionGroup + * The Get function now retrieves the ModeratedBy and ManagedBy properties + by the users' UPN instead of their GUID. * EXOHostedContentFilterRule * Changed logic to retrieve the Rules by name. Using the Policy's name instead. +* EXOIntraOrganizationConnector + * Fixes the DiscoveryEndpoint value from the Get method to include trailing + forward slash. +* EXOMalwareFilterRule + * Fixed an issue retrieving the right value for the Enabled property +* EXOOMEConfiguration + * Fixes an error in the Get method where the ExternalMailExpiryInDays property + wasn't properly returned. +* EXOSafeLinksPolicy + * Deprecated the UseTranslatedNotificationText property * TeamsEmergencyCallRoutingPolicy * Fix deletion of resource FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 index 5897eda34b..24224289d7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 @@ -26,6 +26,14 @@ function Get-TargetResource [System.String] $TargetAutodiscoverEpr, + [Parameter()] + [System.String] + $TargetServiceEpr, + + [Parameter()] + [System.String] + $TargetTenantId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -91,7 +99,7 @@ function Get-TargetResource { try { - $AvailabilityAddressSpaces = Get-AvailabilityAddressSpace -ErrorAction Stop + $AvailabilityAddressSpace = Get-AvailabilityAddressSpace -Identity $ForestName -ErrorAction Stop } catch { @@ -99,17 +107,13 @@ function Get-TargetResource -Exception $_ ` -Source $MyInvocation.MyCommand.ModuleName } - - $AvailabilityAddressSpace = $AvailabilityAddressSpaces | Where-Object -FilterScript { $_.Identity -eq $Identity } if ($null -eq $AvailabilityAddressSpace) { - Write-Verbose -Message "AvailabilityAddressSpace $($Identity) does not exist." + Write-Verbose -Message "AvailabilityAddressSpace $($ForestName) does not exist." return $nullReturn } else { - - if ($Null -eq $AvailabilityAddressSpace.TargetAutodiscoverEpr -or $AvailabilityAddressSpace.TargetAutodiscoverEpr -eq '' ) { $TargetAutodiscoverEpr = '' @@ -123,6 +127,8 @@ function Get-TargetResource Identity = $Identity AccessMethod = $AvailabilityAddressSpace.AccessMethod Credentials = $AvailabilityAddressSpace.Credentials + TargetServiceEpr = $AvailabilityAddressSpace.TargetServiceEpd + TargetTenantId = $AvailabilityAddressSpace.TargetTenantId ForestName = $AvailabilityAddressSpace.ForestName TargetAutodiscoverEpr = $TargetAutodiscoverEpr Credential = $Credential @@ -179,6 +185,14 @@ function Set-TargetResource [System.String] $TargetAutodiscoverEpr, + [Parameter()] + [System.String] + $TargetServiceEpr, + + [Parameter()] + [System.String] + $TargetTenantId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -339,6 +353,14 @@ function Test-TargetResource [System.String] $TargetAutodiscoverEpr, + [Parameter()] + [System.String] + $TargetServiceEpr, + + [Parameter()] + [System.String] + $TargetTenantId, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -399,6 +421,7 @@ function Test-TargetResource $ValuesToCheck.Remove('CertificatePath') | Out-Null $ValuesToCheck.Remove('CertificatePassword') | Out-Null $ValuesToCheck.Remove('ManagedIdentity') | Out-Null + $ValuesToCheck.Remove('Identity') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 index 9bf80ec4b8..f57970c686 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 @@ -54,6 +54,9 @@ function Get-TargetResource -InboundParameters $PSBoundParameters } + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` + -InboundParameters $PSBoundParameters + #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -76,7 +79,8 @@ function Get-TargetResource if ($null -ne $AvailabilityConfigs -and $null -ne $AvailabilityConfigs.OrgWideAccount) { - $AvailabilityConfig = ($AvailabilityConfigs | Where-Object -FilterScript { $_.OrgWideAccount -IMatch $OrgWideAccount }) + $user = Get-MgUser -UserId $OrgWideAccount -ErrorAction Stop + $AvailabilityConfig = ($AvailabilityConfigs | Where-Object -FilterScript { $_.OrgWideAccount -IMatch $user.UserId }) } if ($null -eq $AvailabilityConfig) { @@ -84,7 +88,7 @@ function Get-TargetResource return $nullReturn } $result = @{ - OrgWideAccount = $AvailabilityConfig.OrgWideAccount + OrgWideAccount = $OrgWideAccount Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODistributionGroup/MSFT_EXODistributionGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODistributionGroup/MSFT_EXODistributionGroup.psm1 index 52a5afcf6d..f5add5b03b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODistributionGroup/MSFT_EXODistributionGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODistributionGroup/MSFT_EXODistributionGroup.psm1 @@ -300,6 +300,39 @@ function Get-TargetResource $groupTypeValue = 'Security' } + $ManagedByValue = @() + if ($null -ne $distributionGroup.ManagedBy) + { + foreach ($user in $distributionGroup.ManagedBy) + { + try + { + $user = Get-MgUser -UserId $user -ErrorAction Stop + $ManagedByValue += $user.UserPrincipalName + } + catch + { + Write-Verbose -Message "Couldn't retrieve user {$user}" + } + } + } + + $ModeratedByValue = @() + if ($null -ne $distributionGroup.ModeratedBy) + { + foreach ($user in $distributionGroup.ModeratedBy) + { + try + { + $user = Get-MgUser -UserId $user -ErrorAction Stop + $ModeratedByValue += $user.UserPrincipalName + } + catch + { + Write-Verbose -Message "Couldn't retrieve moderating user {$user}" + } + } + } $result = @{ Identity = $distributionGroup.Identity Alias = $distributionGroup.Alias @@ -308,11 +341,11 @@ function Get-TargetResource Description = $descriptionValue DisplayName = $distributionGroup.DisplayName HiddenGroupMembershipEnabled = $distributionGroup.HiddenGroupMembershipEnabled - ManagedBy = $distributionGroup.ManagedBy + ManagedBy = $ManagedByValue MemberDepartRestriction = $distributionGroup.MemberDepartRestriction MemberJoinRestriction = $distributionGroup.MemberJoinRestriction Members = $distributionGroupMembers.Name - ModeratedBy = $distributionGroup.ModeratedBy + ModeratedBy = $ModeratedByValue ModerationEnabled = $distributionGroup.ModerationEnabled Name = $distributionGroup.Name Notes = $distributionGroup.Notes diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 index 7c98904f0a..1cf252701b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 @@ -50,6 +50,7 @@ function Get-TargetResource [System.Boolean] $DownloadLink = $false, + #DEPRECATED [Parameter()] [System.Boolean] $EnableEndUserSpamNotifications = $false, @@ -302,9 +303,7 @@ function Get-TargetResource $nullReturn.Ensure = 'Absent' try { - $HostedContentFilterPolicies = Get-HostedContentFilterPolicy -ErrorAction Stop - - $HostedContentFilterPolicy = $HostedContentFilterPolicies | Where-Object -FilterScript { $_.Identity -eq $Identity } + $HostedContentFilterPolicy = Get-HostedContentFilterPolicy -Identity $Identity-ErrorAction Stop if ($null -eq $HostedContentFilterPolicy) { Write-Verbose -Message "HostedContentFilterPolicy $($Identity) does not exist." @@ -344,12 +343,14 @@ function Get-TargetResource BulkSpamAction = $HostedContentFilterPolicy.BulkSpamAction BulkThreshold = $HostedContentFilterPolicy.BulkThreshold DownloadLink = $HostedContentFilterPolicy.DownloadLink - EnableEndUserSpamNotifications = $HostedContentFilterPolicy.EnableEndUserSpamNotifications + #Deprecated + #EnableEndUserSpamNotifications = $HostedContentFilterPolicy.EnableEndUserSpamNotifications EnableLanguageBlockList = $HostedContentFilterPolicy.EnableLanguageBlockList EnableRegionBlockList = $HostedContentFilterPolicy.EnableRegionBlockList - EndUserSpamNotificationCustomSubject = $HostedContentFilterPolicy.EndUserSpamNotificationCustomSubject - EndUserSpamNotificationFrequency = $HostedContentFilterPolicy.EndUserSpamNotificationFrequency - EndUserSpamNotificationLanguage = $HostedContentFilterPolicy.EndUserSpamNotificationLanguage + #Deprecated + #EndUserSpamNotificationCustomSubject = $HostedContentFilterPolicy.EndUserSpamNotificationCustomSubject + #EndUserSpamNotificationFrequency = $HostedContentFilterPolicy.EndUserSpamNotificationFrequency + #EndUserSpamNotificationLanguage = $HostedContentFilterPolicy.EndUserSpamNotificationLanguage HighConfidencePhishAction = $HostedContentFilterPolicy.HighConfidencePhishAction HighConfidencePhishQuarantineTag = $HostedContentFilterPolicy.HighConfidencePhishQuarantineTag HighConfidenceSpamAction = $HostedContentFilterPolicy.HighConfidenceSpamAction @@ -1055,6 +1056,10 @@ function Test-TargetResource $ValuesToCheck.Remove('CertificatePath') | Out-Null $ValuesToCheck.Remove('CertificatePassword') | Out-Null $ValuesToCheck.Remove('ManagedIdentity') | Out-Null + $ValuesToCheck.Remove('EnableEndUserSpamNotifications') | Out-Null + $ValuesToCheck.Remove('EndUserSpamNotificationLanguage') | Out-Null + $ValuesToCheck.Remove('EndUserSpamNotificationFrequency') | Out-Null + $ValuesToCheck.Remove('EndUserSpamNotificationCustomSubject') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOIntraOrganizationConnector/MSFT_EXOIntraOrganizationConnector.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOIntraOrganizationConnector/MSFT_EXOIntraOrganizationConnector.psm1 index 935ba37c9b..b70c9d634e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOIntraOrganizationConnector/MSFT_EXOIntraOrganizationConnector.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOIntraOrganizationConnector/MSFT_EXOIntraOrganizationConnector.psm1 @@ -96,6 +96,11 @@ function Get-TargetResource } else { + $DiscoveryEndpointValue = $IntraOrganizationConnector.DiscoveryEndpoint.ToString() + if (-not $DiscoveryEndpointValue.EndsWith('/')) + { + $DiscoveryEndpointValue += '/' + } $result = @{ Identity = $Identity DiscoveryEndpoint = $IntraOrganizationConnector.DiscoveryEndpoint.ToString() diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 index b8a2a11c9b..4b9e2d62c5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 @@ -122,10 +122,15 @@ function Get-TargetResource } else { + $EnabledValue = $false + if ($MalwareFilterRule.State -eq 'Enabled') + { + $EnabledValue = $true + } $result = @{ Identity = $Identity Comments = $MalwareFilterRule.Comments - Enabled = $MalwareFilterRule.Enabled + Enabled = $EnabledValue ExceptIfRecipientDomainIs = $MalwareFilterRule.ExceptIfRecipientDomainIs ExceptIfSentTo = $MalwareFilterRule.ExceptIfSentTo ExceptIfSentToMemberOf = $MalwareFilterRule.ExceptIfSentToMemberOf diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 index a877bc1820..8b49da6bed 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 @@ -105,9 +105,8 @@ function Get-TargetResource try { - $MessageClassifications = Get-MessageClassification -ErrorAction Stop + $MessageClassification = Get-MessageClassification -Identity $Identity -ErrorAction Stop - $MessageClassification = $MessageClassifications | Where-Object -FilterScript { $_.Identity -eq $Identity } if ($null -eq $MessageClassification) { Write-Verbose -Message "Message Classification policy $($Identity) does not exist." diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOMEConfiguration/MSFT_EXOOMEConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOMEConfiguration/MSFT_EXOOMEConfiguration.psm1 index 3e8aaa3100..c9a7c719c6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOMEConfiguration/MSFT_EXOOMEConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOOMEConfiguration/MSFT_EXOOMEConfiguration.psm1 @@ -132,7 +132,7 @@ function Get-TargetResource BackgroundColor = $OMEConfiguration.BackgroundColor DisclaimerText = $OMEConfiguration.DisclaimerText EmailText = $OMEConfiguration.EmailText - ExternalMailExpiryInDays = $OMEConfiguration.ExternalMailExpiryInDays + ExternalMailExpiryInDays = $OMEConfiguration.ExternalMailExpiryInterval.Days # Image = $OMEConfiguration.Image IntroductionText = $OMEConfiguration.IntroductionText OTPEnabled = $OMEConfiguration.OTPEnabled diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSafeLinksPolicy/MSFT_EXOSafeLinksPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSafeLinksPolicy/MSFT_EXOSafeLinksPolicy.psm1 index 892843da04..d6ec4c16ab 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSafeLinksPolicy/MSFT_EXOSafeLinksPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSafeLinksPolicy/MSFT_EXOSafeLinksPolicy.psm1 @@ -127,12 +127,9 @@ function Get-TargetResource $nullReturn.Ensure = 'Absent' try { - Write-Verbose -Message 'Global ExchangeOnlineSession status:' - Write-Verbose -Message "$( Get-PSSession -ErrorAction SilentlyContinue | Where-Object -FilterScript { $_.Name -eq 'ExchangeOnline' } | Out-String)" - try { - $SafeLinksPolicies = Get-SafeLinksPolicy -ErrorAction Stop + $SafeLinksPolicy = Get-SafeLinksPolicy -Identity $Identity -ErrorAction Stop } catch { @@ -141,8 +138,6 @@ function Get-TargetResource -Exception $_ ` -Source $MyInvocation.MyCommand.ModuleName } - - $SafeLinksPolicy = $SafeLinksPolicies | Where-Object -FilterScript { $_.Identity -eq $Identity } if (-not $SafeLinksPolicy) { Write-Verbose -Message "SafeLinksPolicy $($Identity) does not exist." @@ -165,7 +160,8 @@ function Get-TargetResource DisableUrlRewrite = $SafeLinksPolicy.DisableUrlRewrite ScanUrls = $SafeLinksPolicy.ScanUrls TrackClicks = $SafeLinksPolicy.TrackClicks - UseTranslatedNotificationText = $SafeLinksPolicy.UseTranslatedNotificationText + # The Get-SafeLinksPolicy no longer returns this property + # UseTranslatedNotificationText = $SafeLinksPolicy.UseTranslatedNotificationText Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -472,6 +468,7 @@ function Test-TargetResource $ValuesToCheck.Remove('CertificatePath') | Out-Null $ValuesToCheck.Remove('CertificatePassword') | Out-Null $ValuesToCheck.Remove('ManagedIdentity') | Out-Null + $ValuesToCheck.Remove('UseTranslatedNotificationText') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 index fd0ffdf943..28551c5cb8 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/1-Create.ps1 @@ -22,12 +22,8 @@ Configuration Example BulkSpamAction = "MoveToJmf" BulkThreshold = 7 DownloadLink = $False - EnableEndUserSpamNotifications = $False EnableLanguageBlockList = $False EnableRegionBlockList = $False - EndUserSpamNotificationCustomSubject = "" - EndUserSpamNotificationFrequency = 3 - EndUserSpamNotificationLanguage = "Default" HighConfidencePhishAction = "Quarantine" HighConfidenceSpamAction = "MoveToJmf" IncreaseScoreWithBizOrInfoUrls = "Off" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 index ffecda1e04..836aef841f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterPolicy/2-Update.ps1 @@ -22,12 +22,8 @@ Configuration Example BulkSpamAction = "MoveToJmf" BulkThreshold = 7 DownloadLink = $True # Updated Property - EnableEndUserSpamNotifications = $False EnableLanguageBlockList = $False EnableRegionBlockList = $False - EndUserSpamNotificationCustomSubject = "" - EndUserSpamNotificationFrequency = 3 - EndUserSpamNotificationLanguage = "Default" HighConfidencePhishAction = "Quarantine" HighConfidenceSpamAction = "MoveToJmf" IncreaseScoreWithBizOrInfoUrls = "Off" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 index d8f53e8694..af70c51640 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/1-Create.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' @@ -20,7 +21,7 @@ Configuration Example Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Legal Team" + ExceptIfSentToMemberOf = "LegalTeam@$Domain" RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 index 602414c835..b109c3907f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedContentFilterRule/2-Update.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' @@ -20,7 +21,7 @@ Configuration Example Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Legal Team" + ExceptIfSentToMemberOf = "LegalTeam@$Domain" RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 index 9a861d1108..d9db058889 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/1-Create.ps1 @@ -22,7 +22,7 @@ Configuration Example Comments = "Does not apply to Executives" Enabled = $True ExceptIfFrom = "AdeleV@$Domain" - FromMemberOf = 'Executives' + FromMemberOf = "Executives@$Domain" HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 index 36f324d0b3..15fa53328c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOHostedOutboundSpamFilterRule/2-Update.ps1 @@ -22,7 +22,7 @@ Configuration Example Comments = "Does not apply to Executives" Enabled = $False # Updated Property ExceptIfFrom = "AdeleV@$Domain" - FromMemberOf = 'Executives' + FromMemberOf = "Executives@$Domain" HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/1-Create.ps1 index 86dac1533c..5be4191d19 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/1-Create.ps1 @@ -12,13 +12,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRole 'ConfigureManagementRole' { Name = "MyDisplayName" Description = "" - Parent = "contoso.onmicrosoft.com\MyProfileInformation" + Parent = "$Domain\MyProfileInformation" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/2-Update.ps1 index 512cd43c77..d6094d3dca 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOManagementRole/2-Update.ps1 @@ -12,13 +12,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRole 'ConfigureManagementRole' { Name = "MyDisplayName" Description = "Updated Description" # Updated Property - Parent = "contoso.onmicrosoft.com\MyProfileInformation" + Parent = "$Domain\MyProfileInformation" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 index ce73e90fb1..013bc6e2f8 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 @@ -20,7 +20,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR', 'ProxyAddresses, ANR', 'PhoneticGivenName, ANR', 'GivenName, ANR', 'PhoneticSurname, ANR', 'Surname, ANR', 'Account, ANR', 'PhoneticDisplayName, ANR', 'UserInformationDisplayName, ANR', 'ExternalMemberCount, Value', 'TotalMemberCount, Value', 'ModerationEnabled, Value', 'DelivContLength, Value', 'MailTipTranslations, Value', 'ObjectGuid, Value', 'IsOrganizational, Value', 'HabSeniorityIndex, Value', 'DisplayTypeEx, Value', 'SimpleDisplayNameAnsi, Value', 'HomeMdbA, Value', 'Certificate, Value', 'UserSMimeCertificate, Value', 'UserCertificate, Value', 'Comment, Value', 'PagerTelephoneNumber, Value', 'AssistantTelephoneNumber, Value', 'MobileTelephoneNumber, Value', 'PrimaryFaxNumber, Value', 'Home2TelephoneNumberMv, Value', 'Business2TelephoneNumberMv, Value', 'HomeTelephoneNumber, Value', 'TargetAddress, Value', 'PhoneticDepartmentName, Value', 'DepartmentName, Value', 'Assistant, Value', 'PhoneticCompanyName, Value', 'CompanyName, Value', 'Title, Value', 'Country, Value', 'PostalCode, Value', 'StateOrProvince, Value', 'Locality, Value', 'StreetAddress, Value', 'Initials, Value', 'BusinessTelephoneNumber, Value', 'SendRichInfo, Value', 'ObjectType, Value', 'DisplayType, Value', 'RejectMessagesFromDLMembers, Indicator', 'AcceptMessagesOnlyFromDLMembers, Indicator', 'RejectMessagesFrom, Indicator', 'AcceptMessagesOnlyFrom, Indicator', 'UmSpokenName, Indicator', 'ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 index a6e6f375cf..4f7b9083af 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 @@ -20,7 +20,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR', 'ProxyAddresses, ANR', 'PhoneticGivenName, ANR', 'GivenName, ANR', 'PhoneticSurname, ANR', 'Surname, ANR', 'Account, ANR', 'PhoneticDisplayName, ANR', 'UserInformationDisplayName, ANR', 'ExternalMemberCount, Value', 'TotalMemberCount, Value', 'ModerationEnabled, Value', 'DelivContLength, Value', 'MailTipTranslations, Value', 'ObjectGuid, Value', 'IsOrganizational, Value', 'HabSeniorityIndex, Value', 'DisplayTypeEx, Value', 'SimpleDisplayNameAnsi, Value', 'HomeMdbA, Value', 'Certificate, Value', 'UserSMimeCertificate, Value', 'UserCertificate, Value', 'Comment, Value', 'PagerTelephoneNumber, Value', 'AssistantTelephoneNumber, Value', 'MobileTelephoneNumber, Value', 'PrimaryFaxNumber, Value', 'Home2TelephoneNumberMv, Value', 'Business2TelephoneNumberMv, Value', 'HomeTelephoneNumber, Value', 'TargetAddress, Value', 'PhoneticDepartmentName, Value', 'DepartmentName, Value', 'Assistant, Value', 'PhoneticCompanyName, Value', 'CompanyName, Value', 'Title, Value', 'Country, Value', 'PostalCode, Value', 'StateOrProvince, Value', 'Locality, Value', 'StreetAddress, Value', 'Initials, Value', 'BusinessTelephoneNumber, Value', 'SendRichInfo, Value', 'ObjectType, Value', 'DisplayType, Value', 'RejectMessagesFromDLMembers, Indicator', 'AcceptMessagesOnlyFromDLMembers, Indicator', 'RejectMessagesFrom, Indicator', 'AcceptMessagesOnlyFrom, Indicator', 'UmSpokenName, Indicator', 'ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 index a3887a84fa..885d097448 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/1-Create.ps1 @@ -25,7 +25,7 @@ Configuration Example ContentType = "MimeHtmlText" DeliveryReportEnabled = $True DisplaySenderName = $True - DomainName = "*" + DomainName = "contoso.com" IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 index 4aace58ca5..22d9d7249d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 @@ -25,7 +25,7 @@ Configuration Example ContentType = "MimeHtmlText" DeliveryReportEnabled = $True DisplaySenderName = $True - DomainName = "*" + DomainName = "contoso.com" IsInternal = $False LineWrapSize = "Integration" MeetingForwardNotificationEnabled = $False diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 index feab8da8eb..255584dbd0 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/1-Create.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeAttachmentRule 'ConfigureSafeAttachmentRule' @@ -20,9 +21,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 index 419c6f7d0d..6aa8a4a02b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeAttachmentRule/2-Update.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeAttachmentRule 'ConfigureSafeAttachmentRule' @@ -20,9 +21,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/1-Create.ps1 index c0f0456700..1d27ca318e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/1-Create.ps1 @@ -24,7 +24,6 @@ Configuration Example EnableOrganizationBranding = $True EnableSafeLinksForTeams = $True ScanUrls = $True - UseTranslatedNotificationText = $True Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/2-Update.ps1 index 09de5e45b7..ae083d94a0 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksPolicy/2-Update.ps1 @@ -24,7 +24,6 @@ Configuration Example EnableOrganizationBranding = $False # Updated Property EnableSafeLinksForTeams = $True ScanUrls = $True - UseTranslatedNotificationText = $True Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 index 93694876a8..f89887d86b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/1-Create.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeLinksRule 'ConfigureSafeLinksRule' @@ -20,9 +21,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 index a01e4f058d..c86aa8e09a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOSafeLinksRule/2-Update.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeLinksRule 'ConfigureSafeLinksRule' @@ -20,9 +21,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 index 4b79f0fa53..3fb7c0a9fe 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/1-Create.ps1 @@ -13,13 +13,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" - BetweenMemberOf1 = "Sales Team" - BetweenMemberOf2 = "Executives" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 index 8ef3a7d5ae..ebec921bdd 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTransportRule/2-Update.ps1 @@ -13,13 +13,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" - BetweenMemberOf1 = "Sales Team" - BetweenMemberOf2 = "Executives" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." From f16ba5d45150c62571443e6cdfe686b8fb785eeb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 16:42:41 -0500 Subject: [PATCH 042/171] Fixes --- .../Examples/Resources/EXOAntiPhishRule/1-Create.ps1 | 6 ------ .../Examples/Resources/EXOAntiPhishRule/2-Update.ps1 | 5 ----- 2 files changed, 11 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/1-Create.ps1 index e2f6aeeba4..03b2094ac1 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/1-Create.ps1 @@ -18,13 +18,7 @@ Configuration Example EXOAntiPhishRule 'ConfigureAntiPhishRule' { Identity = "Test Rule" - ExceptIfSentToMemberOf = $null - ExceptIfSentTo = $null - SentTo = $null - ExceptIfRecipientDomainIs = $null - Comments = $null AntiPhishPolicy = "Our Rule" - RecipientDomainIs = $null Enabled = $True SentToMemberOf = @("executives@$Domain") Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/2-Update.ps1 index 210bb04776..622f37e92b 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAntiPhishRule/2-Update.ps1 @@ -18,13 +18,8 @@ Configuration Example EXOAntiPhishRule 'ConfigureAntiPhishRule' { Identity = "Test Rule" - ExceptIfSentToMemberOf = $null - ExceptIfSentTo = $null - SentTo = $null - ExceptIfRecipientDomainIs = $null Comments = "This is an updated comment." # Updated Property AntiPhishPolicy = "Our Rule" - RecipientDomainIs = $null Enabled = $True SentToMemberOf = @("executives@$Domain") Ensure = "Present" From 97c7195d206b79cfcd927c56c10ca74004f267c9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 30 Jan 2024 17:18:53 -0500 Subject: [PATCH 043/171] Fixes Unit Tests --- .../MSFT_EXOAvailabilityAddressSpace.psm1 | 6 +-- ...SFT_EXOAvailabilityAddressSpace.schema.mof | 2 +- .../MSFT_EXOHostedContentFilterPolicy.psm1 | 3 +- .../MSFT_EXOMalwareFilterRule.psm1 | 4 +- ...5DSC.EXOAvailabilityAddressSpace.Tests.ps1 | 10 ++--- ...soft365DSC.EXOAvailabilityConfig.Tests.ps1 | 14 ++++--- ...osoft365DSC.EXODistributionGroup.Tests.ps1 | 37 ++++++++++++++++--- ...DSC.EXOHostedContentFilterPolicy.Tests.ps1 | 7 ---- ...osoft365DSC.EXOMalwareFilterRule.Tests.ps1 | 11 ++---- 9 files changed, 54 insertions(+), 40 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 index 24224289d7..614702f42b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 @@ -10,7 +10,7 @@ function Get-TargetResource $Identity, [Parameter()] - [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBBasic', 'InternalProxy')] + [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBToken', 'OrgWideFBBasic', 'InternalProxy')] [System.String] $AccessMethod, @@ -169,7 +169,7 @@ function Set-TargetResource $Identity, [Parameter()] - [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBBasic', 'InternalProxy')] + [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBToken', 'OrgWideFBBasic', 'InternalProxy')] [System.String] $AccessMethod, @@ -337,7 +337,7 @@ function Test-TargetResource $Identity, [Parameter()] - [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBBasic', 'InternalProxy')] + [ValidateSet('PerUserFB', 'OrgWideFB', 'OrgWideFBToken', 'OrgWideFBBasic', 'InternalProxy')] [System.String] $AccessMethod, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof index 12da6f39d9..e7a1374760 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof @@ -3,7 +3,7 @@ class MSFT_EXOAvailabilityAddressSpace : OMI_BaseResource { [Key, Description("The Identity parameter specifies the AvailabilityAddressSpace you want to modify.")] String Identity; - [Write, Description("The AccessMethod parameter specifies how the free/busy data is accessed. Valid values are:PerUserFB, OrgWideFB, OrgWideFBBasic,InternalProxy"), ValueMap{"PerUserFB","OrgWideFB","OrgWideFBBasic","InternalProxy"}, Values{"PerUserFB","OrgWideFB","OrgWideFBBasic","InternalProxy"}] String AccessMethod; + [Write, Description("The AccessMethod parameter specifies how the free/busy data is accessed. Valid values are:PerUserFB, OrgWideFB, OrgWideFBToken, OrgWideFBBasic,InternalProxy"), ValueMap{"PerUserFB","OrgWideFB","OrgWideFBToken","OrgWideFBBasic","InternalProxy"}, Values{"PerUserFB","OrgWideFB","OrgWideFBToken","OrgWideFBBasic","InternalProxy"}] String AccessMethod; [Write, Description("The Credentials parameter specifies the username and password that's used to access the Availability services in the target forest.")] String Credentials; [Write, Description("The ForestName parameter specifies the SMTP domain name of the target forest for users whose free/busy data must be retrieved. If your users are distributed among multiple SMTP domains in the target forest, run the Add-AvailabilityAddressSpace command once for each SMTP domain.")] String ForestName; [Write, Description("The TargetAutodiscoverEpr parameter specifies the Autodiscover URL of Exchange Web Services for the external organization. Exchange uses Autodiscover to automatically detect the correct server endpoint for external requests.")] String TargetAutodiscoverEpr; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 index 1cf252701b..90c58d92c2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOHostedContentFilterPolicy/MSFT_EXOHostedContentFilterPolicy.psm1 @@ -303,7 +303,7 @@ function Get-TargetResource $nullReturn.Ensure = 'Absent' try { - $HostedContentFilterPolicy = Get-HostedContentFilterPolicy -Identity $Identity-ErrorAction Stop + $HostedContentFilterPolicy = Get-HostedContentFilterPolicy -Identity $Identity -ErrorAction Stop if ($null -eq $HostedContentFilterPolicy) { Write-Verbose -Message "HostedContentFilterPolicy $($Identity) does not exist." @@ -407,6 +407,7 @@ function Get-TargetResource } catch { + Write-Verbose -Message $_ New-M365DSCLogEntry -Message 'Error retrieving data:' ` -Exception $_ ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 index 4b9e2d62c5..e04646db5b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMalwareFilterRule/MSFT_EXOMalwareFilterRule.psm1 @@ -112,9 +112,7 @@ function Get-TargetResource $nullReturn.Ensure = 'Absent' try { - $MalwareFilterRules = Get-MalwareFilterRule -ErrorAction Stop - - $MalwareFilterRule = $MalwareFilterRules | Where-Object -FilterScript { $_.Identity -eq $Identity } + $MalwareFilterRule = Get-MalwareFilterRule -Identity $Identity -ErrorAction SilentlyContinue if ($null -eq $MalwareFilterRule) { Write-Verbose -Message "MalwareFilterRule $($Identity) does not exist." diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 index 03e7bd73d9..082ebc201b 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 @@ -57,16 +57,14 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Credential = $Credential Ensure = 'Present' Identity = 'contoso.com' - AccessMethod = 'OrgWideFB' - Credentials = $Null + AccessMethod = 'OrgWideFBToken' ForestName = 'contoso.com' - TargetAutodiscoverEpr = 'http://autodiscover.contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'http://autodiscover.contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'contoso.com' } Mock -CommandName Get-AvailabilityAddressSpace -MockWith { - return @{ - Identity = 'SomeOtherConnector' - } + return $null } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 index 21f2a299cb..15281ce041 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 @@ -52,9 +52,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-AvailabilityConfig -MockWith { - return @{ - OrgWideAccount = 'meganb' - } + return $null } Mock -CommandName Set-AvailabilityConfig -MockWith { @@ -86,12 +84,16 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Ensure = 'Absent' Credential = $Credential } - - Mock -CommandName Get-AvailabilityConfig -MockWith { + + Mock -CommandName Get-MgUser -MockWith { return @{ - OrgWideAccount = 'meganb' + UserPrincipalName = 'johndoe' } } + + Mock -CommandName Get-AvailabilityConfig -MockWith { + return $null + } } It 'Should return Absent from the Get method' { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODistributionGroup.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODistributionGroup.Tests.ps1 index 791f795732..d63570c9af 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODistributionGroup.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODistributionGroup.Tests.ps1 @@ -109,7 +109,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Closed' - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -119,6 +119,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SendModerationNotifications = 'Always' Credential = $Credential } + + + Mock -CommandName Get-MgUser -MockWith { + return @{ + UserPrincipalName = 'john.smith@contoso.com' + } + } Mock -CommandName Get-DistributionGroup -MockWith { return @{ @@ -130,7 +137,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Open' # Drift - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -169,7 +176,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Closed' - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -179,6 +186,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SendModerationNotifications = 'Always' Credential = $Credential } + + Mock -CommandName Get-MgUser -MockWith { + return @{ + UserPrincipalName = 'john.smith@contoso.com' + } + } Mock -CommandName Get-DistributionGroup -MockWith { return @{ @@ -190,7 +203,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Closed' - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -224,7 +237,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Closed' - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -234,6 +247,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { SendModerationNotifications = 'Always' Credential = $Credential } + + Mock -CommandName Get-MgUser -MockWith { + return @{ + UserPrincipalName = 'john.smith@contoso.com' + } + } Mock -CommandName Get-DistributionGroup -MockWith { return @{ @@ -245,7 +264,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ManagedBy = @('john.smith@contoso.com') MemberDepartRestriction = 'Open' MemberJoinRestriction = 'Closed' - ModeratedBy = @('admin@contoso.com') + ModeratedBy = @('john.smith@contoso.com') ModerationEnabled = $False Identity = 'DemoDG' Name = 'DemoDG' @@ -279,6 +298,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ Credential = $Credential } + + Mock -CommandName Get-MgUser -MockWith { + return @{ + UserPrincipalName = 'john.smith@contoso.com' + } + } Mock -CommandName Get-DistributionGroup -MockWith { return @{ diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOHostedContentFilterPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOHostedContentFilterPolicy.Tests.ps1 index 06966ab348..49e1d983d3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOHostedContentFilterPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOHostedContentFilterPolicy.Tests.ps1 @@ -63,7 +63,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { RedirectToRecipients = @() TestModeBccToRecipients = @() QuarantineRetentionPeriod = 15 - EndUserSpamNotificationFrequency = 1 TestModeAction = 'AddXHeader' IncreaseScoreWithImageLinks = 'Off' IncreaseScoreWithNumericIps = 'On' @@ -177,16 +176,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-HostedContentFilterPolicy -MockWith { return @{ - Ensure = 'Present' Identity = 'TestPolicy' - Credential = $Credential AdminDisplayName = 'This ContentFilter policiy is a test' AddXHeaderValue = 'MyCustomSpamHeader' ModifySubjectValue = 'SPAM!' RedirectToRecipients = @() TestModeBccToRecipients = @() QuarantineRetentionPeriod = 15 - EndUserSpamNotificationFrequency = 1 TestModeAction = 'AddXHeader' IncreaseScoreWithImageLinks = 'Off' IncreaseScoreWithNumericIps = 'On' @@ -209,12 +205,9 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { HighConfidencePhishAction = 'Quarantine' HighConfidenceSpamAction = 'Quarantine' SpamAction = 'MoveToJmf' - EnableEndUserSpamNotifications = $true DownloadLink = $false EnableRegionBlockList = $true EnableLanguageBlockList = $true - EndUserSpamNotificationCustomSubject = 'This is SPAM' - EndUserSpamNotificationLanguage = 'Default' BulkThreshold = 5 AllowedSenders = @{ Sender = @( diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMalwareFilterRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMalwareFilterRule.Tests.ps1 index 7e1dd5a1ce..ca6696b7ff 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMalwareFilterRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOMalwareFilterRule.Tests.ps1 @@ -71,9 +71,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-MalwareFilterRule -MockWith { - return @{ - Identity = 'SomeOtherMalwareFilterRule' - } + return $null } } @@ -110,8 +108,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MalwareFilterRule -MockWith { return @{ - Ensure = 'Present' - Credential = $Credential Identity = 'TestMalwareFilterRule' Comments = 'This is a test rule' Enabled = $true @@ -121,6 +117,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { MalwareFilterPolicy = 'Policy1' Priority = '1' RecipientDomainIs = 'contoso.com' + State = 'Enabled' SentTo = @('will@contoso.com', 'bernadette@contoso.org') SentToMemberOf = @('Testgroup3', 'testgroup4') } @@ -152,11 +149,10 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-MalwareFilterRule -MockWith { return @{ - Ensure = 'Present' - Credential = $Credential Identity = 'TestMalwareFilterRule' Comments = 'This is a test rule' Enabled = $true + State = 'Enabled' ExceptIfRecipientDomainIs = 'firma.de' ExceptIfSentTo = 'clausi@contoso.com' ExceptIfSentToMemberOf = 'Testgroup1' @@ -230,6 +226,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ExceptIfSentTo = 'clausi@contoso.com' ExceptIfSentToMemberOf = 'Testgroup1' MalwareFilterPolicy = 'Policy1' + State = 'Enabled' Priority = '2' RecipientDomainIs = 'contoso.com' SentTo = 'will@contoso.com' From 177e05a9a8c2f8ac5fab61aa59c93c0689b6f22a Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 23:55:31 +0000 Subject: [PATCH 044/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOAntiPhishRule.md | 11 ----------- .../resources/exchange/EXOAvailabilityAddressSpace.md | 2 +- .../exchange/EXOHostedContentFilterPolicy.md | 8 -------- .../resources/exchange/EXOHostedContentFilterRule.md | 6 ++++-- .../exchange/EXOHostedOutboundSpamFilterRule.md | 4 ++-- docs/docs/resources/exchange/EXOManagementRole.md | 6 ++++-- docs/docs/resources/exchange/EXOOfflineAddressBook.md | 4 ++-- docs/docs/resources/exchange/EXORemoteDomain.md | 4 ++-- docs/docs/resources/exchange/EXOSafeAttachmentRule.md | 10 ++++++---- docs/docs/resources/exchange/EXOSafeLinksPolicy.md | 2 -- docs/docs/resources/exchange/EXOSafeLinksRule.md | 10 ++++++---- docs/docs/resources/exchange/EXOTransportRule.md | 10 ++++++---- 12 files changed, 33 insertions(+), 44 deletions(-) diff --git a/docs/docs/resources/exchange/EXOAntiPhishRule.md b/docs/docs/resources/exchange/EXOAntiPhishRule.md index f58f4814ba..8b645130f9 100644 --- a/docs/docs/resources/exchange/EXOAntiPhishRule.md +++ b/docs/docs/resources/exchange/EXOAntiPhishRule.md @@ -66,13 +66,7 @@ Configuration Example EXOAntiPhishRule 'ConfigureAntiPhishRule' { Identity = "Test Rule" - ExceptIfSentToMemberOf = $null - ExceptIfSentTo = $null - SentTo = $null - ExceptIfRecipientDomainIs = $null - Comments = $null AntiPhishPolicy = "Our Rule" - RecipientDomainIs = $null Enabled = $True SentToMemberOf = @("executives@$Domain") Ensure = "Present" @@ -103,13 +97,8 @@ Configuration Example EXOAntiPhishRule 'ConfigureAntiPhishRule' { Identity = "Test Rule" - ExceptIfSentToMemberOf = $null - ExceptIfSentTo = $null - SentTo = $null - ExceptIfRecipientDomainIs = $null Comments = "This is an updated comment." # Updated Property AntiPhishPolicy = "Our Rule" - RecipientDomainIs = $null Enabled = $True SentToMemberOf = @("executives@$Domain") Ensure = "Present" diff --git a/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md b/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md index f9230a9cd6..120697856f 100644 --- a/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md +++ b/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md @@ -5,7 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the AvailabilityAddressSpace you want to modify. | | -| **AccessMethod** | Write | String | The AccessMethod parameter specifies how the free/busy data is accessed. Valid values are:PerUserFB, OrgWideFB, OrgWideFBBasic,InternalProxy | `PerUserFB`, `OrgWideFB`, `OrgWideFBBasic`, `InternalProxy` | +| **AccessMethod** | Write | String | The AccessMethod parameter specifies how the free/busy data is accessed. Valid values are:PerUserFB, OrgWideFB, OrgWideFBToken, OrgWideFBBasic,InternalProxy | `PerUserFB`, `OrgWideFB`, `OrgWideFBToken`, `OrgWideFBBasic`, `InternalProxy` | | **Credentials** | Write | String | The Credentials parameter specifies the username and password that's used to access the Availability services in the target forest. | | | **ForestName** | Write | String | The ForestName parameter specifies the SMTP domain name of the target forest for users whose free/busy data must be retrieved. If your users are distributed among multiple SMTP domains in the target forest, run the Add-AvailabilityAddressSpace command once for each SMTP domain. | | | **TargetAutodiscoverEpr** | Write | String | The TargetAutodiscoverEpr parameter specifies the Autodiscover URL of Exchange Web Services for the external organization. Exchange uses Autodiscover to automatically detect the correct server endpoint for external requests. | | diff --git a/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md b/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md index 97cab0bb12..5602e6275a 100644 --- a/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md +++ b/docs/docs/resources/exchange/EXOHostedContentFilterPolicy.md @@ -111,12 +111,8 @@ Configuration Example BulkSpamAction = "MoveToJmf" BulkThreshold = 7 DownloadLink = $False - EnableEndUserSpamNotifications = $False EnableLanguageBlockList = $False EnableRegionBlockList = $False - EndUserSpamNotificationCustomSubject = "" - EndUserSpamNotificationFrequency = 3 - EndUserSpamNotificationLanguage = "Default" HighConfidencePhishAction = "Quarantine" HighConfidenceSpamAction = "MoveToJmf" IncreaseScoreWithBizOrInfoUrls = "Off" @@ -180,12 +176,8 @@ Configuration Example BulkSpamAction = "MoveToJmf" BulkThreshold = 7 DownloadLink = $True # Updated Property - EnableEndUserSpamNotifications = $False EnableLanguageBlockList = $False EnableRegionBlockList = $False - EndUserSpamNotificationCustomSubject = "" - EndUserSpamNotificationFrequency = 3 - EndUserSpamNotificationLanguage = "Default" HighConfidencePhishAction = "Quarantine" HighConfidenceSpamAction = "MoveToJmf" IncreaseScoreWithBizOrInfoUrls = "Off" diff --git a/docs/docs/resources/exchange/EXOHostedContentFilterRule.md b/docs/docs/resources/exchange/EXOHostedContentFilterRule.md index f208dc3fb1..fbfb48f062 100644 --- a/docs/docs/resources/exchange/EXOHostedContentFilterRule.md +++ b/docs/docs/resources/exchange/EXOHostedContentFilterRule.md @@ -61,6 +61,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' @@ -68,7 +69,7 @@ Configuration Example Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Legal Team" + ExceptIfSentToMemberOf = "LegalTeam@$Domain" RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" @@ -94,6 +95,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' @@ -101,7 +103,7 @@ Configuration Example Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Legal Team" + ExceptIfSentToMemberOf = "LegalTeam@$Domain" RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" diff --git a/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md b/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md index d24c221638..6aaeb4d7af 100644 --- a/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md +++ b/docs/docs/resources/exchange/EXOHostedOutboundSpamFilterRule.md @@ -70,7 +70,7 @@ Configuration Example Comments = "Does not apply to Executives" Enabled = $True ExceptIfFrom = "AdeleV@$Domain" - FromMemberOf = 'Executives' + FromMemberOf = "Executives@$Domain" HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential @@ -104,7 +104,7 @@ Configuration Example Comments = "Does not apply to Executives" Enabled = $False # Updated Property ExceptIfFrom = "AdeleV@$Domain" - FromMemberOf = 'Executives' + FromMemberOf = "Executives@$Domain" HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential diff --git a/docs/docs/resources/exchange/EXOManagementRole.md b/docs/docs/resources/exchange/EXOManagementRole.md index 410976566f..5e64a9d88a 100644 --- a/docs/docs/resources/exchange/EXOManagementRole.md +++ b/docs/docs/resources/exchange/EXOManagementRole.md @@ -51,13 +51,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRole 'ConfigureManagementRole' { Name = "MyDisplayName" Description = "" - Parent = "contoso.onmicrosoft.com\MyProfileInformation" + Parent = "$Domain\MyProfileInformation" Ensure = "Present" Credential = $Credscredential } @@ -80,13 +81,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOManagementRole 'ConfigureManagementRole' { Name = "MyDisplayName" Description = "Updated Description" # Updated Property - Parent = "contoso.onmicrosoft.com\MyProfileInformation" + Parent = "$Domain\MyProfileInformation" Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index eb4f547b2a..5c5c2224d8 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -61,7 +61,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR', 'ProxyAddresses, ANR', 'PhoneticGivenName, ANR', 'GivenName, ANR', 'PhoneticSurname, ANR', 'Surname, ANR', 'Account, ANR', 'PhoneticDisplayName, ANR', 'UserInformationDisplayName, ANR', 'ExternalMemberCount, Value', 'TotalMemberCount, Value', 'ModerationEnabled, Value', 'DelivContLength, Value', 'MailTipTranslations, Value', 'ObjectGuid, Value', 'IsOrganizational, Value', 'HabSeniorityIndex, Value', 'DisplayTypeEx, Value', 'SimpleDisplayNameAnsi, Value', 'HomeMdbA, Value', 'Certificate, Value', 'UserSMimeCertificate, Value', 'UserCertificate, Value', 'Comment, Value', 'PagerTelephoneNumber, Value', 'AssistantTelephoneNumber, Value', 'MobileTelephoneNumber, Value', 'PrimaryFaxNumber, Value', 'Home2TelephoneNumberMv, Value', 'Business2TelephoneNumberMv, Value', 'HomeTelephoneNumber, Value', 'TargetAddress, Value', 'PhoneticDepartmentName, Value', 'DepartmentName, Value', 'Assistant, Value', 'PhoneticCompanyName, Value', 'CompanyName, Value', 'Title, Value', 'Country, Value', 'PostalCode, Value', 'StateOrProvince, Value', 'Locality, Value', 'StreetAddress, Value', 'Initials, Value', 'BusinessTelephoneNumber, Value', 'SendRichInfo, Value', 'ObjectType, Value', 'DisplayType, Value', 'RejectMessagesFromDLMembers, Indicator', 'AcceptMessagesOnlyFromDLMembers, Indicator', 'RejectMessagesFrom, Indicator', 'AcceptMessagesOnlyFrom, Indicator', 'UmSpokenName, Indicator', 'ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" @@ -94,7 +94,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR', 'ProxyAddresses, ANR', 'PhoneticGivenName, ANR', 'GivenName, ANR', 'PhoneticSurname, ANR', 'Surname, ANR', 'Account, ANR', 'PhoneticDisplayName, ANR', 'UserInformationDisplayName, ANR', 'ExternalMemberCount, Value', 'TotalMemberCount, Value', 'ModerationEnabled, Value', 'DelivContLength, Value', 'MailTipTranslations, Value', 'ObjectGuid, Value', 'IsOrganizational, Value', 'HabSeniorityIndex, Value', 'DisplayTypeEx, Value', 'SimpleDisplayNameAnsi, Value', 'HomeMdbA, Value', 'Certificate, Value', 'UserSMimeCertificate, Value', 'UserCertificate, Value', 'Comment, Value', 'PagerTelephoneNumber, Value', 'AssistantTelephoneNumber, Value', 'MobileTelephoneNumber, Value', 'PrimaryFaxNumber, Value', 'Home2TelephoneNumberMv, Value', 'Business2TelephoneNumberMv, Value', 'HomeTelephoneNumber, Value', 'TargetAddress, Value', 'PhoneticDepartmentName, Value', 'DepartmentName, Value', 'Assistant, Value', 'PhoneticCompanyName, Value', 'CompanyName, Value', 'Title, Value', 'Country, Value', 'PostalCode, Value', 'StateOrProvince, Value', 'Locality, Value', 'StreetAddress, Value', 'Initials, Value', 'BusinessTelephoneNumber, Value', 'SendRichInfo, Value', 'ObjectType, Value', 'DisplayType, Value', 'RejectMessagesFromDLMembers, Indicator', 'AcceptMessagesOnlyFromDLMembers, Indicator', 'RejectMessagesFrom, Indicator', 'AcceptMessagesOnlyFrom, Indicator', 'UmSpokenName, Indicator', 'ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" diff --git a/docs/docs/resources/exchange/EXORemoteDomain.md b/docs/docs/resources/exchange/EXORemoteDomain.md index f81c377297..3237473427 100644 --- a/docs/docs/resources/exchange/EXORemoteDomain.md +++ b/docs/docs/resources/exchange/EXORemoteDomain.md @@ -84,7 +84,7 @@ Configuration Example ContentType = "MimeHtmlText" DeliveryReportEnabled = $True DisplaySenderName = $True - DomainName = "*" + DomainName = "contoso.com" IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False @@ -130,7 +130,7 @@ Configuration Example ContentType = "MimeHtmlText" DeliveryReportEnabled = $True DisplaySenderName = $True - DomainName = "*" + DomainName = "contoso.com" IsInternal = $False LineWrapSize = "Integration" MeetingForwardNotificationEnabled = $False diff --git a/docs/docs/resources/exchange/EXOSafeAttachmentRule.md b/docs/docs/resources/exchange/EXOSafeAttachmentRule.md index d7dbef3929..1710116f10 100644 --- a/docs/docs/resources/exchange/EXOSafeAttachmentRule.md +++ b/docs/docs/resources/exchange/EXOSafeAttachmentRule.md @@ -60,6 +60,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeAttachmentRule 'ConfigureSafeAttachmentRule' @@ -67,9 +68,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } @@ -93,6 +94,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeAttachmentRule 'ConfigureSafeAttachmentRule' @@ -100,9 +102,9 @@ Configuration Example Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOSafeLinksPolicy.md b/docs/docs/resources/exchange/EXOSafeLinksPolicy.md index 55102a0a47..832c7ee845 100644 --- a/docs/docs/resources/exchange/EXOSafeLinksPolicy.md +++ b/docs/docs/resources/exchange/EXOSafeLinksPolicy.md @@ -76,7 +76,6 @@ Configuration Example EnableOrganizationBranding = $True EnableSafeLinksForTeams = $True ScanUrls = $True - UseTranslatedNotificationText = $True Ensure = 'Present' Credential = $Credscredential } @@ -111,7 +110,6 @@ Configuration Example EnableOrganizationBranding = $False # Updated Property EnableSafeLinksForTeams = $True ScanUrls = $True - UseTranslatedNotificationText = $True Ensure = 'Present' Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOSafeLinksRule.md b/docs/docs/resources/exchange/EXOSafeLinksRule.md index e83e251fc2..a9db3a6dbe 100644 --- a/docs/docs/resources/exchange/EXOSafeLinksRule.md +++ b/docs/docs/resources/exchange/EXOSafeLinksRule.md @@ -60,6 +60,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeLinksRule 'ConfigureSafeLinksRule' @@ -67,9 +68,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } @@ -93,6 +94,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOSafeLinksRule 'ConfigureSafeLinksRule' @@ -100,9 +102,9 @@ Configuration Example Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $False # Updated Property - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOTransportRule.md b/docs/docs/resources/exchange/EXOTransportRule.md index 6908c2b82d..3625f100b5 100644 --- a/docs/docs/resources/exchange/EXOTransportRule.md +++ b/docs/docs/resources/exchange/EXOTransportRule.md @@ -217,13 +217,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" - BetweenMemberOf1 = "Sales Team" - BetweenMemberOf2 = "Executives" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." @@ -251,13 +252,14 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" - BetweenMemberOf1 = "Sales Team" - BetweenMemberOf2 = "Executives" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." From ed91b1356ec248a0a1017b523b68ec86506815a7 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 30 Jan 2024 23:57:24 +0000 Subject: [PATCH 045/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 1df315f69b..46252835fc 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -83,13 +83,7 @@ EXOAntiPhishRule 'ConfigureAntiPhishRule' { Identity = "Test Rule" - ExceptIfSentToMemberOf = $null - ExceptIfSentTo = $null - SentTo = $null - ExceptIfRecipientDomainIs = $null - Comments = $null AntiPhishPolicy = "Our Rule" - RecipientDomainIs = $null Enabled = $True SentToMemberOf = @("executives@$Domain") Ensure = "Present" @@ -223,12 +217,8 @@ BulkSpamAction = "MoveToJmf" BulkThreshold = 7 DownloadLink = $False - EnableEndUserSpamNotifications = $False EnableLanguageBlockList = $False EnableRegionBlockList = $False - EndUserSpamNotificationCustomSubject = "" - EndUserSpamNotificationFrequency = 3 - EndUserSpamNotificationLanguage = "Default" HighConfidencePhishAction = "Quarantine" HighConfidenceSpamAction = "MoveToJmf" IncreaseScoreWithBizOrInfoUrls = "Off" @@ -268,7 +258,7 @@ Identity = "Integration CFR" Comments = "Applies to all users, except when member of HR group" Enabled = $True - ExceptIfSentToMemberOf = "Legal Team" + ExceptIfSentToMemberOf = "LegalTeam@$Domain" RecipientDomainIs = @('contoso.com') HostedContentFilterPolicy = "Integration CFP" Ensure = "Present" @@ -296,7 +286,7 @@ Comments = "Does not apply to Executives" Enabled = $True ExceptIfFrom = "AdeleV@$Domain" - FromMemberOf = 'Executives' + FromMemberOf = "Executives@$Domain" HostedOutboundSpamFilterPolicy = "Integration SFP" Ensure = "Present" Credential = $Credscredential @@ -391,7 +381,7 @@ { Name = "MyDisplayName" Description = "" - Parent = "contoso.onmicrosoft.com\MyProfileInformation" + Parent = "$Domain\MyProfileInformation" Ensure = "Present" Credential = $Credscredential } @@ -479,7 +469,7 @@ { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR', 'ProxyAddresses, ANR', 'PhoneticGivenName, ANR', 'GivenName, ANR', 'PhoneticSurname, ANR', 'Surname, ANR', 'Account, ANR', 'PhoneticDisplayName, ANR', 'UserInformationDisplayName, ANR', 'ExternalMemberCount, Value', 'TotalMemberCount, Value', 'ModerationEnabled, Value', 'DelivContLength, Value', 'MailTipTranslations, Value', 'ObjectGuid, Value', 'IsOrganizational, Value', 'HabSeniorityIndex, Value', 'DisplayTypeEx, Value', 'SimpleDisplayNameAnsi, Value', 'HomeMdbA, Value', 'Certificate, Value', 'UserSMimeCertificate, Value', 'UserCertificate, Value', 'Comment, Value', 'PagerTelephoneNumber, Value', 'AssistantTelephoneNumber, Value', 'MobileTelephoneNumber, Value', 'PrimaryFaxNumber, Value', 'Home2TelephoneNumberMv, Value', 'Business2TelephoneNumberMv, Value', 'HomeTelephoneNumber, Value', 'TargetAddress, Value', 'PhoneticDepartmentName, Value', 'DepartmentName, Value', 'Assistant, Value', 'PhoneticCompanyName, Value', 'CompanyName, Value', 'Title, Value', 'Country, Value', 'PostalCode, Value', 'StateOrProvince, Value', 'Locality, Value', 'StreetAddress, Value', 'Initials, Value', 'BusinessTelephoneNumber, Value', 'SendRichInfo, Value', 'ObjectType, Value', 'DisplayType, Value', 'RejectMessagesFromDLMembers, Indicator', 'AcceptMessagesOnlyFromDLMembers, Indicator', 'RejectMessagesFrom, Indicator', 'AcceptMessagesOnlyFrom, Indicator', 'UmSpokenName, Indicator', 'ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" @@ -676,7 +666,7 @@ ContentType = "MimeHtmlText" DeliveryReportEnabled = $True DisplaySenderName = $True - DomainName = "*" + DomainName = "contoso.com" IsInternal = $False LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False @@ -722,9 +712,9 @@ Identity = "Research Department Attachment Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeAttachmentPolicy = "Marketing Block Attachments" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } @@ -737,7 +727,6 @@ EnableOrganizationBranding = $True EnableSafeLinksForTeams = $True ScanUrls = $True - UseTranslatedNotificationText = $True Ensure = 'Present' Credential = $Credscredential } @@ -746,9 +735,9 @@ Identity = "Research Department URL Rule" Comments = "Applies to Research Department, except managers" Enabled = $True - ExceptIfSentToMemberOf = "Executives" + ExceptIfSentToMemberOf = "Executives@$Domain" SafeLinksPolicy = "Marketing Block URL" - SentToMemberOf = "Legal Team" + SentToMemberOf = "LegalTeam@$Domain" Ensure = "Present" Credential = $Credscredential } @@ -773,8 +762,8 @@ EXOTransportRule 'ConfigureTransportRule' { Name = "Ethical Wall - Sales and Executives Departments" - BetweenMemberOf1 = "Sales Team" - BetweenMemberOf2 = "Executives" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" ExceptIfFrom = "AdeleV@$Domain" ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." From 2925bf71fa3d14780418ea3e86d70c16d339fe42 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Wed, 31 Jan 2024 09:15:33 +0000 Subject: [PATCH 046/171] Added support for Certificate Authentication --- CHANGELOG.md | 3 + .../MSFT_TeamsUserCallingSettings.psm1 | 94 ++++++++++++++++--- .../MSFT_TeamsUserCallingSettings.schema.mof | 6 +- 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0072b6ac1f..e41d2b7bfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ * TeamsEmergencyCallRoutingPolicy * Fix deletion of resource FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) +* TeamsUserCallingSettings + * Add support for Certificate Authentication + FIXES [#3180](https://github.com/microsoft/Microsoft365DSC/issues/3180) * TEAMS * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.psm1 index 040d5b62b2..c9cc4664d5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.psm1 @@ -61,9 +61,25 @@ function Get-TargetResource [System.String] $Ensure = 'Present', - [Parameter(Mandatory = $true)] + [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Calling Policy $($Identity)" @@ -111,6 +127,10 @@ function Get-TargetResource ForwardingTarget = $instance.ForwardingTarget Ensure = 'Present' Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -187,9 +207,25 @@ function Set-TargetResource [System.String] $Ensure = 'Present', - [Parameter(Mandatory = $true)] + [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting Teams User Calling Settings' @@ -297,9 +333,25 @@ function Test-TargetResource [System.String] $Ensure = 'Present', - [Parameter(Mandatory = $true)] + [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -339,9 +391,25 @@ function Export-TargetResource [OutputType([System.String])] param ( - [Parameter(Mandatory = $true)] + [Parameter()] [System.Management.Automation.PSCredential] - $Credential + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -371,9 +439,13 @@ function Export-TargetResource { Write-Host " |---[$i/$($allUsers.Length)] $($user.UserPrincipalName)" -NoNewline $params = @{ - Identity = $user.UserPrincipalName - Ensure = 'Present' - Credential = $Credential + Identity = $user.UserPrincipalName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof index 86a7b83d7b..b73f7d0db3 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof @@ -14,6 +14,8 @@ class MSFT_TeamsUserCallingSettings : OMI_BaseResource [Write, Description("The forwarding target type. Supported values are Voicemail, SingleTarget, MyDelegates and Group. Voicemail is only supported for Immediate forwarding."), ValueMap{"Group","MyDelegates","SingleTarget","Voicemail"}, Values{"Group","MyDelegates","SingleTarget","Voicemail"}] String ForwardingTargetType; [Write, Description("The forwarding target. Supported types of values are ObjectId's, SIP addresses and phone numbers. For phone numbers we support the following types of formats: E.164 (+12065551234 or +1206555000;ext=1234) or non-E.164 like 1234.")] String ForwardingTarget; [Write, Description("Present ensures the policy exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; - [Required, Description("Credentials of the Teams Global Admin."), EmbeddedInstance("MSFT_Credential")] String Credential; - [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Credentials of the Teams Global Admin."), EmbeddedInstance("MSFT_Credential")] String Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; }; From 978303c63526104c42a59eee203ccf9df6fc2372 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Wed, 31 Jan 2024 09:15:47 +0000 Subject: [PATCH 047/171] Missed in previous --- CHANGELOG.md | 2 +- .../MSFT_TeamsUserCallingSettings.schema.mof | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e41d2b7bfd..ab400da4ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,7 +24,7 @@ * Fix deletion of resource FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) * TeamsUserCallingSettings - * Add support for Certificate Authentication + * Added support for Certificate Authentication FIXES [#3180](https://github.com/microsoft/Microsoft365DSC/issues/3180) * TEAMS * Added support for ManagedIdentity Authentication across Teams resources. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof index b73f7d0db3..a3a372cde5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUserCallingSettings/MSFT_TeamsUserCallingSettings.schema.mof @@ -18,4 +18,5 @@ class MSFT_TeamsUserCallingSettings : OMI_BaseResource [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; [Write, Description("Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com")] 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; }; From 1661e0af19e7c18f5cc3e25ede6a02a1ee171aa0 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Wed, 31 Jan 2024 10:35:09 +0100 Subject: [PATCH 048/171] Fixes --- .../MSFT_EXORecipientPermission.psm1 | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 index 95b8ae0583..06759e50af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 @@ -90,14 +90,12 @@ function Get-TargetResource } else { - #Could include a switch for the different propertySets to retrieve https://learn.microsoft.com/en-us/powershell/exchange/cmdlet-property-sets?view=exchange-ps#get-exomailbox-property-sets - #Could include a switch for the different recipientTypeDetails to retrieve - $recipientPermission = Get-EXORecipientPermission -Identity $Identity -Trustee $Trustee -AccessRights $AccessRights -ErrorAction Stop + $recipientPermission = Get-RecipientPermission -Identity $Identity -Trustee $Trustee -AccessRights $AccessRights -ErrorAction Stop } if ($null -eq $recipientPermission) { - Write-Verbose -Message "The specified Recipient Permission doesn't already exist." + Write-Verbose -Message "The specified Recipient Permission doesn't exist." return $nullReturn } @@ -222,6 +220,7 @@ function Set-TargetResource $parameters.Remove('CertificatePassword') | Out-Null $parameters.Remove('ManagedIdentity') | Out-Null $parameters.Remove('Ensure') | Out-Null + $parameters.AccessRights = $AccessRights #Parameters with default values are not part PSBoundParameters # Receipient Permission doesn't exist but it should if ($Ensure -eq 'Present' -and $currentState.Ensure -eq 'Absent') @@ -298,26 +297,28 @@ function Test-TargetResource #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies + $param = $PSBoundParameters + #region Telemetry $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' $CommandName = $MyInvocation.MyCommand $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` -CommandName $CommandName ` - -Parameters $PSBoundParameters + -Parameters $param Add-M365DSCTelemetryEvent -Data $data #endregion Write-Verbose -Message "Testing configuration of Office 365 Recipient permissions $DisplayName" - $currentValues = Get-TargetResource @PSBoundParameters + $currentValues = Get-TargetResource @param Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $currentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $param)" $testResult = Test-M365DSCParameterState -CurrentValues $currentValues ` -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck @('Ensure', 'Identity') + -DesiredValues $param ` + -ValuesToCheck Ensure, Identity, Trustee, AccessRights Write-Verbose -Message "Test-TargetResource returned $testResult" @@ -331,11 +332,11 @@ function Export-TargetResource [CmdletBinding()] param ( - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Identity, - [Parameter(Mandatory = $true)] + [Parameter()] [System.String] $Trustee, @@ -398,7 +399,7 @@ function Export-TargetResource { $Script:ExportMode = $true - [array]$Script:recipientPermissions = Get-EXORecipientPermission -ResultSize Unlimited + [array]$Script:recipientPermissions = Get-RecipientPermission -ResultSize Unlimited $dscContent = '' $i = 1 From 0c96f72614f53437c2ec22ab0312efbe928352ba Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Wed, 31 Jan 2024 10:35:16 +0100 Subject: [PATCH 049/171] Added unit tests --- ...oft365DSC.EXORecipientPermission.Tests.ps1 | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 new file mode 100644 index 0000000000..bd23cf9f61 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 @@ -0,0 +1,161 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource EXORecipientPermission -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 'test@password1' -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 Add-RecipientPermission -MockWith { + } + + Mock -CommandName Remove-RecipientPermission -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + } + + # Test contexts + Context -Name 'Permission doesnt exist and it should' -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential + Identity = 'john.smith' + Trustee = 'john.doe' + } + + Mock -CommandName Get-EXORecipientPermission -MockWith { + return $null + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should return absent from the Get Method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + + It 'Should add the permission in the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Add-RecipientPermission -Exactly 1 + } + } + + Context -Name 'Permission exists and is not the Desired State' -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Present' + Credential = $Credential + Identity = 'john.smith' + Trustee = 'john.doe' + } + + Mock -CommandName Get-RecipientPermission -MockWith { + return $null + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should return present from the Get Method' { + (Get-TargetResource @testParams).Ensure | Should -Be Absent + } + } + + Context -Name 'Permission exist and it should not' -Fixture { + BeforeAll { + $testParams = @{ + Ensure = 'Absent' + Credential = $Credential + Identity = 'john.smith' + Trustee = 'john.doe' + } + + Mock -CommandName Get-RecipientPermission -MockWith { + return @{ + Identity = 'john.smith' + Trustee = 'john.doe' + 'AccessControlType' = 'Allow' + AccessRights = @('SendAs') + IsInherited = $false + InheritanceType = 'None' + } + } + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should return absent from the Get Method' { + (Get-TargetResource @testParams).Ensure | Should -Be Present + } + + It 'Should remove the permission in the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Remove-RecipientPermission -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-RecipientPermission -MockWith { + return @{ + Identity = 'john.smith' + Trustee = 'john.doe' + 'AccessControlType' = 'Allow' + AccessRights = @('SendAs') + IsInherited = $false + InheritanceType = 'None' + } + } + } + + 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 f3e4dbcd523bb14e012772baef5592fb07929ed7 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Wed, 31 Jan 2024 11:05:13 +0100 Subject: [PATCH 050/171] Bug fix --- .../Microsoft365DSC.EXORecipientPermission.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 index bd23cf9f61..ca1f3f0b94 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXORecipientPermission.Tests.ps1 @@ -52,7 +52,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Trustee = 'john.doe' } - Mock -CommandName Get-EXORecipientPermission -MockWith { + Mock -CommandName Get-RecipientPermission -MockWith { return $null } } From 1ccd485a584190b220c2a222beda6354638b8413 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 11:07:40 -0500 Subject: [PATCH 051/171] Fixes for Integration Tests --- .../MSFT_EXOAvailabilityAddressSpace.schema.mof | 2 ++ .../MSFT_EXOAvailabilityConfig.psm1 | 6 +----- .../Resources/EXOAvailabilityAddressSpace/1-Create.ps1 | 5 +++-- .../Resources/EXOAvailabilityAddressSpace/2-Update.ps1 | 5 +++-- .../Examples/Resources/EXODistributionGroup/1-Create.ps1 | 1 - .../Examples/Resources/EXODistributionGroup/2-Update.ps1 | 1 - .../Resources/EXOIntraOrganizationConnector/1-Create.ps1 | 2 +- .../Resources/EXOIntraOrganizationConnector/2-Update.ps1 | 2 +- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof index e7a1374760..504f3b02af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.schema.mof @@ -7,6 +7,8 @@ class MSFT_EXOAvailabilityAddressSpace : OMI_BaseResource [Write, Description("The Credentials parameter specifies the username and password that's used to access the Availability services in the target forest.")] String Credentials; [Write, Description("The ForestName parameter specifies the SMTP domain name of the target forest for users whose free/busy data must be retrieved. If your users are distributed among multiple SMTP domains in the target forest, run the Add-AvailabilityAddressSpace command once for each SMTP domain.")] String ForestName; [Write, Description("The TargetAutodiscoverEpr parameter specifies the Autodiscover URL of Exchange Web Services for the external organization. Exchange uses Autodiscover to automatically detect the correct server endpoint for external requests.")] String TargetAutodiscoverEpr; + [Write, Description("The TargetServiceEpr parameter specifies the Exchange Online Calendar Service URL of the external Microsoft 365 organization that you're trying to read free/busy information from.")] String TargetServiceEpr; + [Write, Description("The TargetTenantID parameter specifies the tenant ID of the external Microsoft 365 organization that you're trying to read free/busy information from.")] String TargetTenantId; [Write, Description("Specifies if this AvailabilityAddressSpace should exist."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; [Write, Description("Credentials of the Exchange Global Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 index f57970c686..a0d4e1ad4f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 @@ -84,7 +84,7 @@ function Get-TargetResource } if ($null -eq $AvailabilityConfig) { - Write-Verbose -Message "Availability config for $($OrgWideAccount) does not exist." + Write-Verbose -Message "Availability config for [$($OrgWideAccount)] does not exist." return $nullReturn } $result = @{ @@ -267,10 +267,6 @@ function Test-TargetResource $ValuesToCheck.Remove('ManagedIdentity') | Out-Null $DesiredValues = $PSBoundParameters - if ($OrgWideAccount.Contains('@')) - { - $DesiredValues.OrgWideAccount = $OrgWideAccount.Split('@')[0] - } $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/1-Create.ps1 index ab8f6d89fa..388e65eab4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/1-Create.ps1 @@ -19,9 +19,10 @@ Configuration Example EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' - AccessMethod = 'OrgWideFB' + AccessMethod = 'OrgWideFBToken' ForestName = 'example.contoso.com' - TargetAutodiscoverEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'o365dsc.onmicrosoft.com' Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/2-Update.ps1 index 1dcd3fef7a..957581c0cc 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAvailabilityAddressSpace/2-Update.ps1 @@ -19,9 +19,10 @@ Configuration Example EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' - AccessMethod = 'OrgWideFBBasic' # Updated Property + AccessMethod = 'OrgWideFBToken' ForestName = 'example.contoso.com' - TargetAutodiscoverEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'contoso.onmicrosoft.com' # Updated Property Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 index adcbd23b3a..ce9a53e436 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/1-Create.ps1 @@ -31,7 +31,6 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 index 997f790410..06744f178c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODistributionGroup/2-Update.ps1 @@ -31,7 +31,6 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/1-Create.ps1 index f670d356e4..141cb1aa07 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/1-Create.ps1 @@ -18,7 +18,7 @@ Configuration Example EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' { Identity = "MainCloudConnector" - DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" Enabled = $True Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/2-Update.ps1 index 34b31fcc80..0fc17035db 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOIntraOrganizationConnector/2-Update.ps1 @@ -18,7 +18,7 @@ Configuration Example EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' { Identity = "MainCloudConnector" - DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" Enabled = $False # Updated Property Ensure = "Present" From 6fa09ee9c7e933ebc5efe4a5c7688509973fd1d6 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 16:21:49 +0000 Subject: [PATCH 052/171] Updated Resources and Cmdlet documentation pages --- .../exchange/EXOAvailabilityAddressSpace.md | 12 ++++++++---- docs/docs/resources/exchange/EXODistributionGroup.md | 2 -- .../exchange/EXOIntraOrganizationConnector.md | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md b/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md index 120697856f..769b0472c4 100644 --- a/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md +++ b/docs/docs/resources/exchange/EXOAvailabilityAddressSpace.md @@ -9,6 +9,8 @@ | **Credentials** | Write | String | The Credentials parameter specifies the username and password that's used to access the Availability services in the target forest. | | | **ForestName** | Write | String | The ForestName parameter specifies the SMTP domain name of the target forest for users whose free/busy data must be retrieved. If your users are distributed among multiple SMTP domains in the target forest, run the Add-AvailabilityAddressSpace command once for each SMTP domain. | | | **TargetAutodiscoverEpr** | Write | String | The TargetAutodiscoverEpr parameter specifies the Autodiscover URL of Exchange Web Services for the external organization. Exchange uses Autodiscover to automatically detect the correct server endpoint for external requests. | | +| **TargetServiceEpr** | Write | String | The TargetServiceEpr parameter specifies the Exchange Online Calendar Service URL of the external Microsoft 365 organization that you're trying to read free/busy information from. | | +| **TargetTenantId** | Write | String | The TargetTenantID parameter specifies the tenant ID of the external Microsoft 365 organization that you're trying to read free/busy information from. | | | **Ensure** | Write | String | Specifies if this AvailabilityAddressSpace should exist. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | @@ -60,9 +62,10 @@ Configuration Example EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' - AccessMethod = 'OrgWideFB' + AccessMethod = 'OrgWideFBToken' ForestName = 'example.contoso.com' - TargetAutodiscoverEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'o365dsc.onmicrosoft.com' Ensure = 'Present' Credential = $Credscredential } @@ -92,9 +95,10 @@ Configuration Example EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' - AccessMethod = 'OrgWideFBBasic' # Updated Property + AccessMethod = 'OrgWideFBToken' ForestName = 'example.contoso.com' - TargetAutodiscoverEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'contoso.onmicrosoft.com' # Updated Property Ensure = 'Present' Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXODistributionGroup.md b/docs/docs/resources/exchange/EXODistributionGroup.md index cef3fac485..27939036b9 100644 --- a/docs/docs/resources/exchange/EXODistributionGroup.md +++ b/docs/docs/resources/exchange/EXODistributionGroup.md @@ -110,7 +110,6 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; @@ -154,7 +153,6 @@ Configuration Example ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; diff --git a/docs/docs/resources/exchange/EXOIntraOrganizationConnector.md b/docs/docs/resources/exchange/EXOIntraOrganizationConnector.md index 6bcf11c824..5aae4b5039 100644 --- a/docs/docs/resources/exchange/EXOIntraOrganizationConnector.md +++ b/docs/docs/resources/exchange/EXOIntraOrganizationConnector.md @@ -59,7 +59,7 @@ Configuration Example EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' { Identity = "MainCloudConnector" - DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" Enabled = $True Ensure = "Present" @@ -90,7 +90,7 @@ Configuration Example EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' { Identity = "MainCloudConnector" - DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" Enabled = $False # Updated Property Ensure = "Present" From 7daca6a1e31f3322a8ceb98d09f721910e39df4c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 16:23:21 +0000 Subject: [PATCH 053/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 46252835fc..32ad469f95 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -127,9 +127,10 @@ EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' - AccessMethod = 'OrgWideFB' + AccessMethod = 'OrgWideFBToken' ForestName = 'example.contoso.com' - TargetAutodiscoverEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'o365dsc.onmicrosoft.com' Ensure = 'Present' Credential = $Credscredential } @@ -172,7 +173,6 @@ ModerationEnabled = $False; Identity = "DemoDG"; Name = "DemoDG"; - OrganizationalUnit = "$Domain"; PrimarySmtpAddress = "demodg@$Domain"; RequireSenderAuthenticationEnabled = $True; SendModerationNotifications = "Always"; @@ -308,7 +308,7 @@ EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' { Identity = "MainCloudConnector" - DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" Enabled = $True Ensure = "Present" From f5aa08cd5b25df50730a77bec02e2086786a5c9f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 12:18:12 -0500 Subject: [PATCH 054/171] Fixes for Integration --- .../MSFT_EXOAvailabilityAddressSpace.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 index 614702f42b..9a3623e303 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 @@ -127,7 +127,7 @@ function Get-TargetResource Identity = $Identity AccessMethod = $AvailabilityAddressSpace.AccessMethod Credentials = $AvailabilityAddressSpace.Credentials - TargetServiceEpr = $AvailabilityAddressSpace.TargetServiceEpd + TargetServiceEpr = $AvailabilityAddressSpace.TargetServiceEpr TargetTenantId = $AvailabilityAddressSpace.TargetTenantId ForestName = $AvailabilityAddressSpace.ForestName TargetAutodiscoverEpr = $TargetAutodiscoverEpr From d04f452ae82db87637ee656c7ab14ca23f500b5a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 12:44:59 -0500 Subject: [PATCH 055/171] Update 1-Create.ps1 --- .../Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 index 013bc6e2f8..2cc34fefe6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 @@ -20,7 +20,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From 53b56f1bdba92f371ff4e255c111ce5ed0f35544 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 17:45:41 +0000 Subject: [PATCH 056/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOOfflineAddressBook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index 5c5c2224d8..4e4a012f37 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -61,7 +61,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From 453cd7218de35daa17ef79d1f61d10772b3f64f9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 12:45:51 -0500 Subject: [PATCH 057/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 index 4f7b9083af..caedea9743 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 @@ -20,7 +20,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" From 04954627e50dfdb3cbf734ff0688abe3fe07aff0 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 17:46:39 +0000 Subject: [PATCH 058/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOOfflineAddressBook.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index 4e4a012f37..dbbac9f5a7 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -94,7 +94,7 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" From 55dfb0b8b5e912561c88cd440f3be062195821ae Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 17:47:35 +0000 Subject: [PATCH 059/171] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 32ad469f95..696bb4592a 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -469,7 +469,7 @@ { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','DisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') + ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From 23a1028af19274fc37ddbf118955c3e93f8fe156 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 12:58:50 -0500 Subject: [PATCH 060/171] Update 1-Create.ps1 --- .../Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 index 2cc34fefe6..d59a79deae 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 @@ -20,7 +20,6 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From 6c8e89636765e811dbf99a78bb12226d4b838fd2 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 31 Jan 2024 12:59:01 -0500 Subject: [PATCH 061/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 index caedea9743..3a05445e78 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 @@ -20,7 +20,6 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" From f7352d7a3e2024f0243eaa5558133aa0493a7527 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 17:59:47 +0000 Subject: [PATCH 062/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOOfflineAddressBook.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index dbbac9f5a7..cdadd9da05 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -61,7 +61,6 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From 16a997d5ec6adb3cfcfa9f7355f98ba8755bd20c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 18:03:47 +0000 Subject: [PATCH 063/171] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 696bb4592a..8ae6b2b387 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -469,7 +469,6 @@ { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" From f39fe956045fd78431ebdfd37e553bbabb636b81 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 31 Jan 2024 18:05:46 +0000 Subject: [PATCH 064/171] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 1137 +++++++++++++++++ 1 file changed, 1137 insertions(+) create mode 100644 Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 new file mode 100644 index 0000000000..25081b9bf3 --- /dev/null +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -0,0 +1,1137 @@ + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential + ) + + Configuration Master + { + param + ( + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $Credscredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] + Node Localhost + { + EXOAcceptedDomain 'O365DSCDomain' + { + Identity = $Domain + DomainType = "Authoritative" + OutboundOnly = $true # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOActiveSyncDeviceAccessRule 'ConfigureActiveSyncDeviceAccessRule' + { + Identity = "ContosoPhone(DeviceOS)" + Characteristic = "DeviceModel" # Updated Property + QueryString = "iOS 6.1 10B145" + AccessLevel = "Allow" + Ensure = "Present" + Credential = $Credscredential + } + EXOAddressBookPolicy 'ConfigureAddressBookPolicy' + { + Name = "All Fabrikam ABP" + AddressLists = "\All Users" + RoomList = "\All Rooms" + OfflineAddressBook = "\Default Offline Address Book" + GlobalAddressList = "\Default Global Address List" + Ensure = "Present" + Credential = $Credscredential + } + EXOAddressList 'HRUsersAddressList' + { + Name = "HR Users" + ConditionalCompany = "Contoso" + ConditionalDepartment = "HR2" # Updated Property + ConditionalStateOrProvince = "US" + IncludedRecipients = "AllRecipients" + Ensure = "Present" + Credential = $Credscredential + } + EXOAntiPhishPolicy 'ConfigureAntiphishPolicy' + { + Identity = "Our Rule" + MakeDefault = $null + PhishThresholdLevel = 2 # Updated Property + EnableTargetedDomainsProtection = $null + Enabled = $null + TargetedDomainsToProtect = $null + EnableSimilarUsersSafetyTips = $null + ExcludedDomains = $null + TargetedDomainActionRecipients = $null + EnableMailboxIntelligence = $null + EnableSimilarDomainsSafetyTips = $null + AdminDisplayName = "" + AuthenticationFailAction = "MoveToJmf" + TargetedUserProtectionAction = "NoAction" + TargetedUsersToProtect = $null + EnableTargetedUserProtection = $null + ExcludedSenders = $null + EnableOrganizationDomainsProtection = $null + EnableUnusualCharactersSafetyTips = $null + TargetedUserActionRecipients = $null + Ensure = "Present" + Credential = $Credscredential + } + EXOAntiPhishRule 'ConfigureAntiPhishRule' + { + Identity = "Test Rule" + Comments = "This is an updated comment." # Updated Property + AntiPhishPolicy = "Our Rule" + Enabled = $True + SentToMemberOf = @("executives@$Domain") + Ensure = "Present" + Credential = $Credscredential + } + EXOApplicationAccessPolicy 'ConfigureApplicationAccessPolicy' + { + Identity = "Integration Policy" + AccessRight = "DenyAccess" + AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' + PolicyScopeGroupId = "IntegrationMailEnabled@$Domain" + Description = "Engineering Group Policy Updated" # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOAtpPolicyForO365 'ConfigureAntiPhishPolicy' + { + IsSingleInstance = "Yes" + EnableATPForSPOTeamsODB = $true + Ensure = "Present" + Credential = $Credscredential + } + EXOAuthenticationPolicy 'ConfigureAuthenticationPolicy' + { + Identity = "Block Basic Auth" + AllowBasicAuthActiveSync = $False + AllowBasicAuthAutodiscover = $False + AllowBasicAuthImap = $False + AllowBasicAuthMapi = $True # Updated Property + AllowBasicAuthOfflineAddressBook = $False + AllowBasicAuthOutlookService = $False + AllowBasicAuthPop = $False + AllowBasicAuthPowerShell = $False + AllowBasicAuthReportingWebServices = $False + AllowBasicAuthRpc = $False + AllowBasicAuthSmtp = $False + AllowBasicAuthWebServices = $False + Ensure = "Present" + Credential = $Credscredential + } + EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' + { + UserName = "AdeleV@$Domain" + AuthenticationPolicyName = "Test Policy" # Updaqted Property + Ensure = "Present" + Credential = $Credscredential + } + EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' + { + Identity = 'Contoso.com' + AccessMethod = 'OrgWideFBToken' + ForestName = 'example.contoso.com' + TargetServiceEpr = 'https://contoso.com/autodiscover/autodiscover.xml' + TargetTenantId = 'contoso.onmicrosoft.com' # Updated Property + Ensure = 'Present' + Credential = $Credscredential + } + EXOAvailabilityConfig 'ConfigureAvailabilityConfig' + { + OrgWideAccount = "alexW@$Domain" # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOCalendarProcessing 'CalendarProcessing' + { + AddAdditionalResponse = $False; + AddNewRequestsTentatively = $True; + AddOrganizerToSubject = $False; # Updated Property + AllBookInPolicy = $True; + AllowConflicts = $False; + AllowRecurringMeetings = $True; + AllRequestInPolicy = $False; + AllRequestOutOfPolicy = $False; + AutomateProcessing = "AutoUpdate"; + BookingType = "Standard"; + BookingWindowInDays = 180; + BookInPolicy = @(); + ConflictPercentageAllowed = 0; + Credential = $credsCredential; + DeleteAttachments = $True; + DeleteComments = $True; + DeleteNonCalendarItems = $True; + DeleteSubject = $True; + EnableAutoRelease = $False; + EnableResponseDetails = $True; + EnforceCapacity = $False; + EnforceSchedulingHorizon = $True; + Ensure = "Present"; + ForwardRequestsToDelegates = $True; + Identity = "AdeleV"; + MaximumConflictInstances = 0; + MaximumDurationInMinutes = 1440; + MinimumDurationInMinutes = 0; + OrganizerInfo = $True; + PostReservationMaxClaimTimeInMinutes = 10; + ProcessExternalMeetingMessages = $False; + RemoveCanceledMeetings = $False; + RemoveForwardedMeetingNotifications = $False; + RemoveOldMeetingMessages = $False; + RemovePrivateProperty = $True; + RequestInPolicy = @("AlexW@$Domain"); + ResourceDelegates = @(); + ScheduleOnlyDuringWorkHours = $False; + TentativePendingApproval = $True; + } + EXOCASMailboxPlan 'ConfigureCASMailboxPlan' + { + ActiveSyncEnabled = $True + OwaMailboxPolicy = "OwaMailboxPolicy-Default" + PopEnabled = $False # Updated Property + Identity = 'ExchangeOnlineEnterprise' + ImapEnabled = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOCASMailboxSettings 'AdeleVCasMailboxSettings' + { + ActiveSyncAllowedDeviceIDs = @() + ActiveSyncBlockedDeviceIDs = @() + ActiveSyncDebugLogging = $False + ActiveSyncEnabled = $True + ActiveSyncMailboxPolicy = 'Demo EXO Mobile Device Policy Default' + ActiveSyncSuppressReadReceipt = $False + EwsEnabled = $True + Identity = 'AdeleV' + ImapEnabled = $True # Updated Property + ImapForceICalForCalendarRetrievalOption = $False + ImapMessagesRetrievalMimeFormat = 'BestBodyFormat' + ImapSuppressReadReceipt = $False + ImapUseProtocolDefaults = $True + MacOutlookEnabled = $True + MAPIEnabled = $True + OutlookMobileEnabled = $True + OWAEnabled = $True + OWAforDevicesEnabled = $True + OwaMailboxPolicy = 'OwaMailboxPolicy-Default' + PopEnabled = $False + PopForceICalForCalendarRetrievalOption = $True + PopMessagesRetrievalMimeFormat = 'BestBodyFormat' + PopSuppressReadReceipt = $False + PopUseProtocolDefaults = $True + PublicFolderClientAccess = $False + ShowGalAsDefaultView = $True + UniversalOutlookEnabled = $True + Ensure = 'Present' + Credential = $Credscredential + } + EXOClientAccessRule 'ConfigureClientAccessRule' + { + Action = "AllowAccess" + UserRecipientFilter = $null + ExceptAnyOfAuthenticationTypes = @() + ExceptUsernameMatchesAnyOfPatterns = @() + AnyOfAuthenticationTypes = @() + UsernameMatchesAnyOfPatterns = @() + Identity = "Always Allow Remote PowerShell" + Priority = 1 + AnyOfProtocols = @("RemotePowerShell") + Enabled = $False # Updated Property + ExceptAnyOfProtocols = @() + ExceptAnyOfClientIPAddressesOrRanges = @() + AnyOfClientIPAddressesOrRanges = @() + Ensure = "Present" + Credential = $Credscredential + } + EXODataClassification 'ConfigureDataClassification' + { + Description = "Detects formatted and unformatted Canadian social insurance number."; + Ensure = "Present"; + Identity = "a2f29c85-ecb8-4514-a610-364790c0773e"; + IsDefault = $True; + Locale = "en-US"; + Name = "Canada Social Insurance Number"; + Credential = $Credscredential + } + EXODistributionGroup 'DemoDG' + { + Alias = "demodg"; + BccBlocked = $True; # Updated Property + BypassNestedModerationEnabled = $False; + DisplayName = "My Demo DG"; + Ensure = "Present"; + HiddenGroupMembershipEnabled = $True; + ManagedBy = @("adeleV@$Domain"); + MemberDepartRestriction = "Open"; + MemberJoinRestriction = "Closed"; + ModeratedBy = @("alexW@$Domain"); + ModerationEnabled = $False; + Identity = "DemoDG"; + Name = "DemoDG"; + PrimarySmtpAddress = "demodg@$Domain"; + RequireSenderAuthenticationEnabled = $True; + SendModerationNotifications = "Always"; + Credential = $Credscredential + } + EXODkimSigningConfig 'ConfigureDKIMSigning' + { + KeySize = 1024 + Identity = $Domain + HeaderCanonicalization = "Relaxed" + Enabled = $False # Updated Property + BodyCanonicalization = "Relaxed" + AdminDisplayName = "" + Ensure = "Present" + Credential = $Credscredential + } + EXOEmailAddressPolicy 'ConfigureEmailAddressPolicy' + { + Name = "Integration Policy" + EnabledEmailAddressTemplates = @("SMTP:@$Domain") + EnabledPrimarySMTPAddressTemplate = "@$Domain" + ManagedByFilter = "" + Priority = 2 # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOGlobalAddressList 'ConfigureGlobalAddressList' + { + Name = "Contoso Human Resources in Washington" + ConditionalCompany = "Contoso" + ConditionalDepartment = "Finances" # Updated Property + ConditionalStateOrProvince = "Washington" + Ensure = "Present" + Credential = $Credscredential + } + EXOGroupSettings 'TestGroup' + { + DisplayName = "Test Group"; + AccessType = "Public"; + AlwaysSubscribeMembersToCalendarEvents = $False; + AuditLogAgeLimit = "90.00:00:00"; + AutoSubscribeNewMembers = $False; + CalendarMemberReadOnly = $False; + ConnectorsEnabled = $False; # Updated Property + Credential = $Credscredential; + HiddenFromAddressListsEnabled = $True; + HiddenFromExchangeClientsEnabled = $True; + InformationBarrierMode = "Open"; + Language = "en-US"; + MaxReceiveSize = "36 MB (37,748,736 bytes)"; + MaxSendSize = "35 MB (36,700,160 bytes)"; + ModerationEnabled = $False; + Notes = "My Notes"; + PrimarySmtpAddress = "TestGroup@$Domain"; + RequireSenderAuthenticationEnabled = $True; + SubscriptionEnabled = $False; + } + EXOHostedConnectionFilterPolicy 'ConfigureHostedConnectionFilterPolicy' + { + Identity = "Default" + AdminDisplayName = "" + EnableSafeList = $True # Updated Property + IPAllowList = @() + IPBlockList = @() + MakeDefault = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOHostedContentFilterPolicy 'ConfigureHostedContentFilterPolicy' + { + Identity = "Integration CFP" + AddXHeaderValue = "" + AdminDisplayName = "" + BulkSpamAction = "MoveToJmf" + BulkThreshold = 7 + DownloadLink = $True # Updated Property + EnableLanguageBlockList = $False + EnableRegionBlockList = $False + HighConfidencePhishAction = "Quarantine" + HighConfidenceSpamAction = "MoveToJmf" + IncreaseScoreWithBizOrInfoUrls = "Off" + IncreaseScoreWithImageLinks = "Off" + IncreaseScoreWithNumericIps = "Off" + IncreaseScoreWithRedirectToOtherPort = "Off" + InlineSafetyTipsEnabled = $True + LanguageBlockList = @() + MakeDefault = $False + MarkAsSpamBulkMail = "On" + MarkAsSpamEmbedTagsInHtml = "Off" + MarkAsSpamEmptyMessages = "Off" + MarkAsSpamFormTagsInHtml = "Off" + MarkAsSpamFramesInHtml = "Off" + MarkAsSpamFromAddressAuthFail = "Off" + MarkAsSpamJavaScriptInHtml = "Off" + MarkAsSpamNdrBackscatter = "Off" + MarkAsSpamObjectTagsInHtml = "Off" + MarkAsSpamSensitiveWordList = "Off" + MarkAsSpamSpfRecordHardFail = "Off" + MarkAsSpamWebBugsInHtml = "Off" + ModifySubjectValue = "" + PhishSpamAction = "MoveToJmf" + PhishZapEnabled = $True + QuarantineRetentionPeriod = 15 + RedirectToRecipients = @() + RegionBlockList = @() + SpamAction = "MoveToJmf" + SpamZapEnabled = $True + TestModeAction = "None" + TestModeBccToRecipients = @() + Ensure = "Present" + Credential = $Credscredential + } + EXOHostedContentFilterRule 'ConfigureHostedContentFilterRule' + { + Identity = "Integration CFR" + Comments = "Applies to all users, except when member of HR group" + Enabled = $False # Updated Property + ExceptIfSentToMemberOf = "LegalTeam@$Domain" + RecipientDomainIs = @('contoso.com') + HostedContentFilterPolicy = "Integration CFP" + Ensure = "Present" + Credential = $Credscredential + } + EXOHostedOutboundSpamFilterPolicy 'HostedOutboundSpamFilterPolicy' + { + Identity = "Integration SFP" + ActionWhenThresholdReached = "BlockUserForToday" + AdminDisplayName = "" + AutoForwardingMode = "Automatic" + BccSuspiciousOutboundAdditionalRecipients = @() + BccSuspiciousOutboundMail = $False + NotifyOutboundSpam = $False + NotifyOutboundSpamRecipients = @() + RecipientLimitExternalPerHour = 0 + RecipientLimitInternalPerHour = 1 # Updated Property + RecipientLimitPerDay = 0 + Ensure = "Present" + Credential = $Credscredential + } + EXOHostedOutboundSpamFilterRule 'ConfigureHostedOutboundSpamFilterRule' + { + Identity = "Contoso Executives" + Comments = "Does not apply to Executives" + Enabled = $False # Updated Property + ExceptIfFrom = "AdeleV@$Domain" + FromMemberOf = "Executives@$Domain" + HostedOutboundSpamFilterPolicy = "Integration SFP" + Ensure = "Present" + Credential = $Credscredential + } + EXOInboundConnector 'ConfigureInboundConnector' + { + Identity = "Integration Inbound Connector" + CloudServicesMailEnabled = $False + Comment = "Inbound connector for Integration" + ConnectorSource = "Default" + ConnectorType = "Partner" + Enabled = $False # Updated Property + RequireTls = $True + SenderDomains = "*.contoso.com" + TlsSenderCertificateName = "contoso.com" + Ensure = "Present" + Credential = $Credscredential + } + EXOIntraOrganizationConnector 'ConfigureIntraOrganizationConnector' + { + Identity = "MainCloudConnector" + DiscoveryEndpoint = "https://ExternalDiscovery.Contoso.com/" + TargetAddressDomains = "Cloud1.contoso.com","Cloud2.contoso.com" + Enabled = $False # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOIRMConfiguration 'ConfigureIRMConfiguration' + { + IsSingleInstance = 'Yes' + AutomaticServiceUpdateEnabled = $True + AzureRMSLicensingEnabled = $True + DecryptAttachmentForEncryptOnly = $True + EDiscoverySuperUserEnabled = $True + EnablePdfEncryption = $True + InternalLicensingEnabled = $True + JournalReportDecryptionEnabled = $True + RejectIfRecipientHasNoRights = $True + SearchEnabled = $True + SimplifiedClientAccessDoNotForwardDisabled = $True + SimplifiedClientAccessEnabled = $True + SimplifiedClientAccessEncryptOnlyDisabled = $True + TransportDecryptionSetting = 'Mandatory' + Ensure = 'Present' + Credential = $Credscredential + } + EXOJournalRule 'CreateJournalRule' + { + Enabled = $False # Updated Property + JournalEmailAddress = "AdeleV@$Domain" + Name = "Send to Adele" + RuleScope = "Global" + Ensure = "Present" + Credential = $Credscredential + } + EXOMailboxAutoReplyConfiguration 'EXOMailboxAutoReplyConfiguration' + { + AutoDeclineFutureRequestsWhenOOF = $False; + AutoReplyState = "Disabled"; + CreateOOFEvent = $False; + Credential = $Credscredential; + DeclineAllEventsForScheduledOOF = $False; + DeclineEventsForScheduledOOF = $True; # Updated Property + DeclineMeetingMessage = ""; + EndTime = "1/23/2024 3:00:00 PM"; + Ensure = "Present"; + ExternalAudience = "All"; + ExternalMessage = ""; + Identity = "AdeleV@$Domain"; + InternalMessage = ""; + OOFEventSubject = ""; + StartTime = "1/22/2024 3:00:00 PM"; + } + EXOMailboxCalendarFolder 'JohnCalendarFolder' + { + Credential = $credsCredential; + DetailLevel = "AvailabilityOnly"; + Ensure = "Present"; + Identity = "AdeleV:\Calendar"; + PublishDateRangeFrom = "ThreeMonths"; + PublishDateRangeTo = "ThreeMonths"; + PublishEnabled = $True; # Updated Property + SearchableUrlEnabled = $False; + } + EXOMailboxPermission 'TestPermission' + { + AccessRights = @("FullAccess","ReadPermission"); + Credential = $credsCredential; + Deny = $True; # Updated Property + Ensure = "Present"; + Identity = "AdeleV"; + InheritanceType = "All"; + User = "NT AUTHORITY\SELF"; + } + EXOMailboxPlan 'ConfigureMailboxPlan' + { + Ensure = "Present"; + Identity = "Integration Plan"; + IssueWarningQuota = "98 GB (105,226,698,752 bytes)"; + MaxReceiveSize = "25 MB (26,214,400 bytes)"; + MaxSendSize = "25 MB (26,214,400 bytes)"; + ProhibitSendQuota = "99 GB (106,300,440,576 bytes)"; + ProhibitSendReceiveQuota = "15 GB (16,106,127,360 bytes)"; # Updated Property + RetainDeletedItemsFor = "14.00:00:00"; + RoleAssignmentPolicy = "Default Role Assignment Policy"; + Credential = $Credscredential + } + EXOMailboxSettings 'OttawaTeamMailboxSettings' + { + DisplayName = 'Ottawa Employees' + TimeZone = 'Eastern Standard Time' + Locale = 'en-US' # Updated Property + Ensure = 'Present' + Credential = $Credscredential + } + EXOMailContact 'TestMailContact' + { + Alias = 'TestMailContact' + Credential = $Credscredential + DisplayName = 'My Test Contact' + Ensure = 'Present' + ExternalEmailAddress = 'SMTP:test@tailspintoys.com' + MacAttachmentFormat = 'BinHex' + MessageBodyFormat = 'TextAndHtml' + MessageFormat = 'Mime' + ModeratedBy = @() + ModerationEnabled = $false + Name = 'My Test Contact' + OrganizationalUnit = $Domain + SendModerationNotifications = 'Always' + UsePreferMessageFormat = $false # Updated Property + CustomAttribute1 = 'Custom Value 1' + ExtensionCustomAttribute5 = 'Extension Custom Value 1', 'Extension Custom Value 2' + } + EXOMailTips 'OrgWideMailTips' + { + Organization = $Domain + MailTipsAllTipsEnabled = $True + MailTipsGroupMetricsEnabled = $False # Updated Property + MailTipsLargeAudienceThreshold = 100 + MailTipsMailboxSourcedTipsEnabled = $True + MailTipsExternalRecipientsTipsEnabled = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOMalwareFilterPolicy 'ConfigureMalwareFilterPolicy' + { + Identity = "IntegrationMFP" + CustomNotifications = $False + EnableExternalSenderAdminNotifications = $False + EnableFileFilter = $False + EnableInternalSenderAdminNotifications = $False + FileTypeAction = "Quarantine" + FileTypes = @("ace", "ani", "app", "cab", "docm", "exe", "iso", "jar", "jnlp", "reg", "scr", "vbe", "vbs") + QuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $False # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOMalwareFilterRule 'ConfigureMalwareFilterRule' + { + Identity = "Contoso Recipients" + MalwareFilterPolicy = "IntegrationMFP" + Comments = "Apply the filter to all Contoso users" + Enabled = $False # Updated Property + RecipientDomainIs = "contoso.com" + Ensure = "Present" + Credential = $Credscredential + } + EXOManagementRole 'ConfigureManagementRole' + { + Name = "MyDisplayName" + Description = "Updated Description" # Updated Property + Parent = "$Domain\MyProfileInformation" + Ensure = "Present" + Credential = $Credscredential + } + EXOManagementRoleAssignment 'AssignManagementRole' + { + Credential = $credsCredential; + Ensure = "Present"; + Name = "MyManagementRoleAssignment"; + Role = "UserApplication"; + User = "AlexW@$Domain"; # Updated Property + } + EXOMessageClassification 'ConfigureMessageClassification' + { + Identity = "Contoso Message Classification" + Name = "Contoso Message Classification" + DisplayName = "Contoso Message Classification" + DisplayPrecedence = "Highest" + PermissionMenuVisible = $True + RecipientDescription = "Shown to receipients" + SenderDescription = "Shown to senders" + RetainClassificationEnabled = $False # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOMobileDeviceMailboxPolicy 'ConfigureMobileDeviceMailboxPolicy' + { + Name = "Default" + AllowApplePushNotifications = $True + AllowBluetooth = "Allow" + AllowBrowser = $False # Updated Property + AllowCamera = $True + AllowConsumerEmail = $True + AllowDesktopSync = $True + AllowExternalDeviceManagement = $False + AllowGooglePushNotifications = $True + AllowHTMLEmail = $True + AllowInternetSharing = $True + AllowIrDA = $True + AllowMicrosoftPushNotifications = $True + AllowMobileOTAUpdate = $True + AllowNonProvisionableDevices = $True + AllowPOPIMAPEmail = $True + AllowRemoteDesktop = $True + AllowSimplePassword = $True + AllowSMIMEEncryptionAlgorithmNegotiation = "AllowAnyAlgorithmNegotiation" + AllowSMIMESoftCerts = $True + AllowStorageCard = $True + AllowTextMessaging = $True + AllowUnsignedApplications = $True + AllowUnsignedInstallationPackages = $True + AllowWiFi = $True + AlphanumericPasswordRequired = $False + ApprovedApplicationList = @() + AttachmentsEnabled = $True + DeviceEncryptionEnabled = $False + DevicePolicyRefreshInterval = "Unlimited" + IrmEnabled = $True + IsDefault = $True + MaxAttachmentSize = "Unlimited" + MaxCalendarAgeFilter = "All" + MaxEmailAgeFilter = "All" + MaxEmailBodyTruncationSize = "Unlimited" + MaxEmailHTMLBodyTruncationSize = "Unlimited" + MaxInactivityTimeLock = "Unlimited" + MaxPasswordFailedAttempts = "Unlimited" + MinPasswordComplexCharacters = 1 + PasswordEnabled = $False + PasswordExpiration = "Unlimited" + PasswordHistory = 0 + PasswordRecoveryEnabled = $False + RequireDeviceEncryption = $False + RequireEncryptedSMIMEMessages = $False + RequireEncryptionSMIMEAlgorithm = "TripleDES" + RequireManualSyncWhenRoaming = $False + RequireSignedSMIMEAlgorithm = "SHA1" + RequireSignedSMIMEMessages = $False + RequireStorageCardEncryption = $False + UnapprovedInROMApplicationList = @() + UNCAccessEnabled = $True + WSSAccessEnabled = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOOfflineAddressBook 'ConfigureOfflineAddressBook' + { + Name = "Integration Address Book" + AddressLists = @('\Offline Global Address List') + DiffRetentionPeriod = "30" + IsDefault = $false # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOOMEConfiguration 'ConfigureOMEConfiguration' + { + Identity = "Contoso Marketing" + BackgroundColor = "0x00FFFF00" + DisclaimerText = "Encryption security disclaimer." + EmailText = "Encrypted message enclosed." + ExternalMailExpiryInDays = 1 # Updated Property + IntroductionText = "You have received an encypted message" + OTPEnabled = $True + PortalText = "This portal is encrypted." + SocialIdSignIn = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' + { + Identity = 'Contoso' + Comment = 'Mail for Contoso. Updated' # Updated Property + HybridDomains = 'contoso.com', 'sales.contoso.com' + InboundConnector = 'Inbound to Contoso' + OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' + OrganizationName = 'Contoso' + OutboundConnector = 'Outbound to Contoso' + Ensure = 'Present' + Credential = $Credscredential + } + EXOOrganizationConfig 'EXOOrganizationConfig' + { + IsSingleInstance = "Yes" + ElcProcessingDisabled = $False + DefaultPublicFolderProhibitPostQuota = "13 KB (13,312 bytes)" + VisibleMeetingUpdateProperties = "Location,AllProperties:15" + BookingsEnabled = $True + ExchangeNotificationRecipients = @() + EwsEnabled = $null + LinkPreviewEnabled = $True + FocusedInboxOn = $null + AsyncSendEnabled = $True + EwsAllowEntourage = $null + RemotePublicFolderMailboxes = @() + AuditDisabled = $False + EwsAllowMacOutlook = $null + ConnectorsEnabledForTeams = $True + DefaultPublicFolderIssueWarningQuota = "13 KB (13,312 bytes)" + MailTipsMailboxSourcedTipsEnabled = $True + EndUserDLUpgradeFlowsDisabled = $False + DistributionGroupDefaultOU = $null + OutlookPayEnabled = $True + EwsAllowOutlook = $null + DefaultAuthenticationPolicy = $null + DistributionGroupNameBlockedWordsList = @() + ConnectorsEnabled = $True + DefaultPublicFolderAgeLimit = $null + OutlookMobileGCCRestrictionsEnabled = $False + ActivityBasedAuthenticationTimeoutEnabled = $True + ConnectorsEnabledForYammer = $True + HierarchicalAddressBookRoot = $null + DefaultPublicFolderMaxItemSize = "13 KB (13,312 bytes)" + MailTipsLargeAudienceThreshold = 25 + ConnectorsActionableMessagesEnabled = $True + ExchangeNotificationEnabled = $True + ActivityBasedAuthenticationTimeoutWithSingleSignOnEnabled = $True + DirectReportsGroupAutoCreationEnabled = $False + OAuth2ClientProfileEnabled = $True + AppsForOfficeEnabled = $True + PublicFoldersEnabled = "Local" + WebPushNotificationsDisabled = $False + MailTipsGroupMetricsEnabled = $True + DefaultPublicFolderMovedItemRetention = "07.00:00:00" + DistributionGroupNamingPolicy = "" + DefaultPublicFolderDeletedItemRetention = "30.00:00:00" + MailTipsAllTipsEnabled = $True + LeanPopoutEnabled = $False + PublicComputersDetectionEnabled = $False + ByteEncoderTypeFor7BitCharsets = 0 + ConnectorsEnabledForOutlook = $True + WebSuggestedRepliesDisabled = $False + PublicFolderShowClientControl = $False + ActivityBasedAuthenticationTimeoutInterval = "06:00:00" + BookingsSocialSharingRestricted = $False + DefaultGroupAccessType = "Private" + IPListBlocked = @() + SmtpActionableMessagesEnabled = $True + SiteMailboxCreationURL = $null + BookingsPaymentsEnabled = $False + MailTipsExternalRecipientsTipsEnabled = $False + AutoExpandingArchive = $null + ConnectorsEnabledForSharepoint = $True + ReadTrackingEnabled = $False + Credential = $Credscredential + } + EXOOrganizationRelationship 'ConfigureOrganizationRelationship' + { + Name = "Contoso" + ArchiveAccessEnabled = $False # Updated Property + DeliveryReportEnabled = $True + DomainNames = "mail.contoso.com" + Enabled = $True + FreeBusyAccessEnabled = $True + FreeBusyAccessLevel = "AvailabilityOnly" + MailboxMoveEnabled = $True + MailTipsAccessEnabled = $True + MailTipsAccessLevel = "None" + PhotosEnabled = $True + TargetApplicationUri = "mail.contoso.com" + TargetAutodiscoverEpr = "https://mail.contoso.com/autodiscover/autodiscover.svc/wssecurity" + Ensure = "Present" + Credential = $Credscredential + } + EXOOutboundConnector 'ConfigureOutboundConnector' + { + Identity = "Contoso Outbound Connector" + AllAcceptedDomains = $False + CloudServicesMailEnabled = $False + Comment = "Outbound connector to Contoso" + ConnectorSource = "Default" + ConnectorType = "Partner" + Enabled = $False # Updated Property + IsTransportRuleScoped = $False + RecipientDomains = "contoso.com" + RouteAllMessagesViaOnPremises = $False + TlsDomain = "*.contoso.com" + TlsSettings = "DomainValidation" + UseMxRecord = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOOwaMailboxPolicy 'ConfigureOwaMailboxPolicy' + { + Name = "OwaMailboxPolicy-Integration" + ActionForUnknownFileAndMIMETypes = "ForceSave" + ActiveSyncIntegrationEnabled = $True + AdditionalStorageProvidersAvailable = $True + AllAddressListsEnabled = $True + AllowCopyContactsToDeviceAddressBook = $True + AllowedFileTypes = @(".rpmsg",".xlsx",".xlsm",".xlsb",".tiff",".pptx",".pptm",".ppsx",".ppsm",".docx",".docm",".zip",".xls",".wmv",".wma",".wav",".vsd",".txt",".tif",".rtf",".pub",".ppt",".png",".pdf",".one",".mp3",".jpg",".gif",".doc",".bmp",".avi") + AllowedMimeTypes = @("image/jpeg","image/png","image/gif","image/bmp") + BlockedFileTypes = @(".settingcontent-ms",".printerexport",".appcontent-ms",".appref-ms",".vsmacros",".website",".msh2xml",".msh1xml",".diagcab",".webpnp",".ps2xml",".ps1xml",".mshxml",".gadget",".theme",".psdm1",".mhtml",".cdxml",".xbap",".vhdx",".pyzw",".pssc",".psd1",".psc2",".psc1",".msh2",".msh1",".jnlp",".aspx",".appx",".xnk",".xml",".xll",".wsh",".wsf",".wsc",".wsb",".vsw",".vst",".vss",".vhd",".vbs",".vbp",".vbe",".url",".udl",".tmp",".shs",".shb",".sct",".scr",".scf",".reg",".pyz",".pyw",".pyo",".pyc",".pst",".ps2",".ps1",".prg",".prf",".plg",".pif",".pcd",".ops",".msu",".mst",".msp",".msi",".msh",".msc",".mht",".mdz",".mdw",".mdt",".mde",".mdb",".mda",".mcf",".maw",".mav",".mau",".mat",".mas",".mar",".maq",".mam",".mag",".maf",".mad",".lnk",".ksh",".jse",".jar",".its",".isp",".ins",".inf",".htc",".hta",".hpj",".hlp",".grp",".fxp",".exe",".der",".csh",".crt",".cpl",".com",".cnt",".cmd",".chm",".cer",".bat",".bas",".asx",".asp",".app",".apk",".adp",".ade",".ws",".vb",".py",".pl",".js") + BlockedMimeTypes = @("application/x-javascript","application/javascript","application/msaccess","x-internet-signup","text/javascript","application/xml","application/prg","application/hta","text/scriplet","text/xml") + ClassicAttachmentsEnabled = $True + ConditionalAccessPolicy = "Off" + DefaultTheme = "" + DirectFileAccessOnPrivateComputersEnabled = $True + DirectFileAccessOnPublicComputersEnabled = $False # Updated Property + DisplayPhotosEnabled = $True + ExplicitLogonEnabled = $True + ExternalImageProxyEnabled = $True + ForceSaveAttachmentFilteringEnabled = $False + ForceSaveFileTypes = @(".vsmacros",".ps2xml",".ps1xml",".mshxml",".gadget",".psc2",".psc1",".aspx",".wsh",".wsf",".wsc",".vsw",".vst",".vss",".vbs",".vbe",".url",".tmp",".swf",".spl",".shs",".shb",".sct",".scr",".scf",".reg",".pst",".ps2",".ps1",".prg",".prf",".plg",".pif",".pcd",".ops",".mst",".msp",".msi",".msh",".msc",".mdz",".mdw",".mdt",".mde",".mdb",".mda",".maw",".mav",".mau",".mat",".mas",".mar",".maq",".mam",".mag",".maf",".mad",".lnk",".ksh",".jse",".its",".isp",".ins",".inf",".hta",".hlp",".fxp",".exe",".dir",".dcr",".csh",".crt",".cpl",".com",".cmd",".chm",".cer",".bat",".bas",".asx",".asp",".app",".adp",".ade",".ws",".vb",".js") + ForceSaveMimeTypes = @("Application/x-shockwave-flash","Application/octet-stream","Application/futuresplash","Application/x-director") + ForceWacViewingFirstOnPrivateComputers = $False + ForceWacViewingFirstOnPublicComputers = $False + FreCardsEnabled = $True + GlobalAddressListEnabled = $True + GroupCreationEnabled = $True + InstantMessagingEnabled = $True + InstantMessagingType = "Ocs" + InterestingCalendarsEnabled = $True + IRMEnabled = $True + IsDefault = $True + JournalEnabled = $True + LocalEventsEnabled = $False + LogonAndErrorLanguage = 0 + NotesEnabled = $True + NpsSurveysEnabled = $True + OnSendAddinsEnabled = $False + OrganizationEnabled = $True + OutboundCharset = "AutoDetect" + OutlookBetaToggleEnabled = $True + OWALightEnabled = $True + PersonalAccountCalendarsEnabled = $True + PhoneticSupportEnabled = $False + PlacesEnabled = $True + PremiumClientEnabled = $True + PrintWithoutDownloadEnabled = $True + PublicFoldersEnabled = $True + RecoverDeletedItemsEnabled = $True + ReferenceAttachmentsEnabled = $True + RemindersAndNotificationsEnabled = $True + ReportJunkEmailEnabled = $True + RulesEnabled = $True + SatisfactionEnabled = $True + SaveAttachmentsToCloudEnabled = $True + SearchFoldersEnabled = $True + SetPhotoEnabled = $True + SetPhotoURL = "" + SignaturesEnabled = $True + SkipCreateUnifiedGroupCustomSharepointClassification = $True + TeamSnapCalendarsEnabled = $True + TextMessagingEnabled = $True + ThemeSelectionEnabled = $True + UMIntegrationEnabled = $True + UseGB18030 = $False + UseISO885915 = $False + UserVoiceEnabled = $True + WacEditingEnabled = $True + WacExternalServicesEnabled = $True + WacOMEXEnabled = $False + WacViewingOnPrivateComputersEnabled = $True + WacViewingOnPublicComputersEnabled = $True + WeatherEnabled = $True + WebPartsFrameOptionsType = "SameOrigin" + Ensure = "Present" + Credential = $Credscredential + } + EXOPartnerApplication 'ConfigurePartnerApplication' + { + Name = "HRApp" + ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" + Enabled = $False # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOPerimeterConfiguration 'ConfigurePerimeterConfiguration' + { + IsSingleInstance = 'Yes' + GatewayIPAddresses = '123.0.0.1' + Ensure = 'Present' + Credential = $Credscredential + } + EXOPlace 'TestPlace' + { + AudioDeviceName = "MyAudioDevice"; + Capacity = 16; # Updated Property + City = ""; + Credential = $Credscredential + DisplayDeviceName = "DisplayDeviceName"; + Ensure = 'Present' + Identity = "Hood@$Domain"; + IsWheelChairAccessible = $True; + MTREnabled = $False; + ParentType = "None"; + Phone = "555-555-5555"; + Tags = @("Tag1", "Tag2"); + VideoDeviceName = "VideoDevice"; + } + EXOPolicyTipConfig 'ConfigurePolicyTipConfig' + { + Name = "en\NotifyOnly" + Value = "This message contains content that is restricted by Contoso company policy. Updated" # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + EXOQuarantinePolicy 'ConfigureQuarantinePolicy' + { + EndUserQuarantinePermissionsValue = 87; + ESNEnabled = $True; # Updated Property + Identity = "$Domain\DefaultFullAccessPolicy"; + Ensure = "Present" + Credential = $Credscredential + } + EXORemoteDomain '583b0b70-b45d-401f-98a6-0e7fa8434946' + { + Identity = "Integration" + AllowedOOFType = "External" + AutoForwardEnabled = $True + AutoReplyEnabled = $False # Updated Property + ByteEncoderTypeFor7BitCharsets = "Undefined" + CharacterSet = "iso-8859-1" + ContentType = "MimeHtmlText" + DeliveryReportEnabled = $True + DisplaySenderName = $True + DomainName = "contoso.com" + IsInternal = $False + LineWrapSize = "Integration" + MeetingForwardNotificationEnabled = $False + Name = "Default" + NonMimeCharacterSet = "iso-8859-1" + PreferredInternetCodePageForShiftJis = "Undefined" + TargetDeliveryDomain = $False + TrustedMailInboundEnabled = $False + TrustedMailOutboundEnabled = $False + UseSimpleDisplayName = $False + Ensure = "Present" + Credential = $Credscredential + } + EXOReportSubmissionPolicy 'ConfigureReportSubmissionPolicy' + { + IsSingleInstance = 'Yes' + DisableQuarantineReportingOption = $False + EnableCustomNotificationSender = $False + EnableOrganizationBranding = $False + EnableReportToMicrosoft = $True + EnableThirdPartyAddress = $False + EnableUserEmailNotification = $False + PostSubmitMessageEnabled = $True + PreSubmitMessageEnabled = $True + ReportJunkToCustomizedAddress = $False + ReportNotJunkToCustomizedAddress = $False + ReportPhishToCustomizedAddress = $False + Ensure = "Present" + Credential = $Credscredential + } + EXOReportSubmissionRule 'ConfigureReportSubmissionRule' + { + IsSingleInstance = 'Yes' + Identity = "DefaultReportSubmissionRule" + Comments = "This is my default rule" + SentTo = "submission@contoso.com" + Ensure = "Present" + Credential = $Credscredential + } + EXOResourceConfiguration 'ConfigureResourceConfiguration' + { + IsSingleInstance = 'Yes' + ResourcePropertySchema = @('Room/TV', 'Equipment/Laptop') + Ensure = 'Present' + Credential = $Credscredential + } + EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' + { + Name = "Integration Policy" + Description = "This policy grants end users the permission to set their options in Outlook on the web and perform other self-administration tasks." + IsDefault = $False # Updated Property + Roles = @("My Marketplace Apps","MyVoiceMail","MyDistributionGroups","MyRetentionPolicies","MyContactInformation","MyBaseOptions","MyTextMessaging","MyDistributionGroupMembership","MyProfileInformation","My Custom Apps","My ReadWriteMailbox Apps") + Ensure = "Present" + Credential = $Credscredential + } + EXORoleGroup 'ConfigureRoleGroup' + { + Name = "Contoso Role Group" + Description = "Address Lists Role for Exchange Administrators. Updated" # Updated Property + Members = @("Exchange Administrator") + Roles = @("Address Lists") + Ensure = "Present" + Credential = $Credscredential + } + EXOSafeAttachmentPolicy 'ConfigureSafeAttachmentPolicy' + { + Identity = "Marketing Block Attachments" + Enable = $False # Updated Property + Redirect = $True + RedirectAddress = "admin@$Domain" + Ensure = "Present" + Credential = $Credscredential + } + EXOSafeAttachmentRule 'ConfigureSafeAttachmentRule' + { + Identity = "Research Department Attachment Rule" + Comments = "Applies to Research Department, except managers" + Enabled = $False # Updated Property + ExceptIfSentToMemberOf = "Executives@$Domain" + SafeAttachmentPolicy = "Marketing Block Attachments" + SentToMemberOf = "LegalTeam@$Domain" + Ensure = "Present" + Credential = $Credscredential + } + EXOSafeLinksPolicy 'ConfigureSafeLinksPolicy' + { + Identity = 'Marketing Block URL' + AdminDisplayName = 'Marketing Block URL' + CustomNotificationText = 'Blocked URLs for Marketing' + DeliverMessageAfterScan = $True + EnableOrganizationBranding = $False # Updated Property + EnableSafeLinksForTeams = $True + ScanUrls = $True + Ensure = 'Present' + Credential = $Credscredential + } + EXOSafeLinksRule 'ConfigureSafeLinksRule' + { + Identity = "Research Department URL Rule" + Comments = "Applies to Research Department, except managers" + Enabled = $False # Updated Property + ExceptIfSentToMemberOf = "Executives@$Domain" + SafeLinksPolicy = "Marketing Block URL" + SentToMemberOf = "LegalTeam@$Domain" + Ensure = "Present" + Credential = $Credscredential + } + EXOSharedMailbox 'SharedMailbox' + { + DisplayName = "Integration" + PrimarySMTPAddress = "Integration@$Domain" + EmailAddresses = @("IntegrationSM@$Domain", "IntegrationSM2@$Domain") + Alias = "IntegrationSM" + Ensure = "Present" + Credential = $Credscredential + } + EXOSharingPolicy 'ConfigureSharingPolicy' + { + Name = "Integration Sharing Policy" + Default = $False # Updated Property + Domains = @("Anonymous:CalendarSharingFreeBusyReviewer", "*:CalendarSharingFreeBusySimple") + Enabled = $True + Ensure = "Present" + Credential = $Credscredential + } + EXOTransportConfig 'EXOTransportConfig ' + { + IsSingleInstance = "Yes"; + AddressBookPolicyRoutingEnabled = $True; + ClearCategories = $True; + ConvertDisclaimerWrapperToEml = $False; + DSNConversionMode = "PreserveDSNBody"; + ExternalDelayDsnEnabled = $True; + ExternalDsnLanguageDetectionEnabled = $True; + ExternalDsnSendHtml = $True; + ExternalPostmasterAddress = "postmaster@contoso.com"; + HeaderPromotionModeSetting = "NoCreate"; + InternalDelayDsnEnabled = $True; + InternalDsnLanguageDetectionEnabled = $True; + InternalDsnSendHtml = $True; + JournalingReportNdrTo = "<>"; + JournalMessageExpirationDays = 0; + MaxRecipientEnvelopeLimit = "Unlimited"; + ReplyAllStormBlockDurationHours = 6; + ReplyAllStormDetectionMinimumRecipients = 2500; + ReplyAllStormDetectionMinimumReplies = 10; + ReplyAllStormProtectionEnabled = $True; + Rfc2231EncodingEnabled = $False; + SmtpClientAuthenticationDisabled = $True; + Credential = $Credscredential + } + EXOTransportRule 'ConfigureTransportRule' + { + Name = "Ethical Wall - Sales and Executives Departments" + BetweenMemberOf1 = "SalesTeam@$Domain" + BetweenMemberOf2 = "Executives@$Domain" + ExceptIfFrom = "AdeleV@$Domain" + ExceptIfSubjectContainsWords = "Press Release","Corporate Communication" + RejectMessageReasonText = "Messages sent between the Sales and Brokerage departments are strictly prohibited." + Enabled = $False # Updated Property + Ensure = "Present" + Credential = $Credscredential + } + } + } + + $ConfigurationData = @{ + AllNodes = @( + @{ + NodeName = "Localhost" + PSDSCAllowPlaintextPassword = $true + } + ) + } + + # Compile and deploy configuration + try + { + Master -ConfigurationData $ConfigurationData -Credscredential $Credential + Start-DscConfiguration Master -Wait -Force -Verbose -ErrorAction Stop + } + catch + { + throw $_ + } From 107bd8623fcb5194b0ab3ee9b8ad3d985316434b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 1 Feb 2024 19:24:36 -0500 Subject: [PATCH 065/171] Release 1.24.131.1 --- CHANGELOG.md | 5 +- .../MSFT_EXOAcceptedDomain.psm1 | 11 +- .../MSFT_EXOAddressList.psm1 | 12 +- .../MSFT_EXOAvailabilityAddressSpace.psm1 | 20 +-- .../MSFT_EXOGlobalAddressList.psm1 | 18 ++- .../2-Update.ps1 | 21 --- .../EXOCASMailboxSettings/2-Update.ps1 | 7 +- .../EXOCalendarProcessing/2-Update.ps1 | 2 +- .../EXOEmailAddressPolicy/2-Update.ps1 | 4 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 138 ++++++------------ .../M365DSCStringEncoding.psm1 | 14 +- .../Modules/M365DSCErrorHandler.psm1 | 7 +- .../Modules/M365DSCReverse.psm1 | 93 +++++++----- .../Modules/M365DSCTelemetryEngine.psm1 | 4 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 17 ++- 15 files changed, 171 insertions(+), 202 deletions(-) delete mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0072b6ac1f..0c40168611 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.131.1 * EXOAvailabilityAddressSpace * Added support for the TargetServiceEpr and TargetTenantId parameters. @@ -27,6 +27,9 @@ * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES * Updated MSCloudLoginAssistant dependencies to version 1.1.10. +* MISC + * Change the way to Export encoding is done so that it no longer relies + on the Get-DSCResource function. # 1.24.124.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 index 6fc5d8d6d7..53797d3961 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 @@ -87,14 +87,11 @@ function Get-TargetResource try { Write-Verbose -Message 'Getting all Accepted Domain' - $AllAcceptedDomains = Get-AcceptedDomain -ErrorAction Stop - - Write-Verbose -Message 'Filtering Accepted Domain list by Identity' - $AcceptedDomain = $AllAcceptedDomains | Where-Object -FilterScript { $_.Identity -eq $Identity } + $AllAcceptedDomain = Get-AcceptedDomain -Identity $Identity -ErrorAction SilentlyContinue if ($null -eq $AcceptedDomain) { - Write-Verbose -Message "AcceptedDomain configuration for $($Identity) does not exist." + Write-Verbose -Message "AcceptedDomain configuration for {$($Identity)} does not exist." return $nullReturn } else @@ -151,12 +148,10 @@ function Set-TargetResource $Ensure = 'Present', [Parameter()] - [ValidateScript( { $false -eq $_ })] [System.Boolean] $MatchSubDomains = $false, [Parameter()] - [ValidateScript( { $false -eq $_ })] [System.Boolean] $OutboundOnly = $false, @@ -223,7 +218,7 @@ function Set-TargetResource OutboundOnly = $OutboundOnly } - Write-Verbose -Message "Setting AcceptedDomain for $($Identity) with values: $(Convert-M365DscHashtableToString -Hashtable $AcceptedDomainParams)" + Write-Verbose -Message "Setting AcceptedDomain for {$($Identity)} with values: $(Convert-M365DscHashtableToString -Hashtable $AcceptedDomainParams)" Set-AcceptedDomain @AcceptedDomainParams } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAddressList/MSFT_EXOAddressList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAddressList/MSFT_EXOAddressList.psm1 index 60468be205..d046f1751e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAddressList/MSFT_EXOAddressList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAddressList/MSFT_EXOAddressList.psm1 @@ -483,11 +483,19 @@ function Set-TargetResource ConditionalCustomAttribute9 = $ConditionalCustomAttribute9 ConditionalDepartment = $ConditionalDepartment ConditionalStateOrProvince = $ConditionalStateOrProvince - DisplayName = $DisplayName IncludedRecipients = $IncludedRecipients - RecipientFilter = $RecipientFilter Confirm = $false } + + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $SetAddressListParams.Add('DisplayName', $DisplayName) + } + + if (-not [System.String]::IsNullOrEmpty($RecipientFilter)) + { + $SetAddressListParams.Add('RecipientFilter', $RecipientFilter) + } } Write-Verbose -Message "Setting Address List '$($Name)' with values: $(Convert-M365DscHashtableToString -Hashtable $SetAddressListParams)" Set-AddressList @SetAddressListParams diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 index 9a3623e303..d7f80154ca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 @@ -243,18 +243,8 @@ function Set-TargetResource $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` -InboundParameters $PSBoundParameters - try - { - $AvailabilityAddressSpaces = Get-AvailabilityAddressSpace -ea stop - } - catch - { - New-M365DSCLogEntry -Message "Couldn't get AvailabilityAddressSpaces" ` - -Exception $_ ` - -Source $MyInvocation.MyCommand.ModuleName - } + $currentInstance = Get-TargetResource @PSBoundParameters - $AvailabilityAddressSpace = $AvailabilityAddressSpaces | Where-Object -FilterScript { $_.Identity -eq $Identity } $AvailabilityAddressSpaceParams = [System.Collections.Hashtable]($PSBoundParameters) $AvailabilityAddressSpaceParams.Remove('Ensure') | Out-Null $AvailabilityAddressSpaceParams.Remove('Credential') | Out-Null @@ -265,7 +255,7 @@ function Set-TargetResource $AvailabilityAddressSpaceParams.Remove('CertificatePassword') | Out-Null $AvailabilityAddressSpaceParams.Remove('ManagedIdentity') | Out-Null - if (('Present' -eq $Ensure ) -and ($null -eq $AvailabilityAddressSpace)) + if ('Present' -eq $Ensure -and $currentInstance.Ensure -eq 'Absent') { Write-Verbose -Message "Creating AvailabilityAddressSpace $($Identity)." # AvailabilityAddressSpace doe not have a new-AvailabilityAddressSpace cmdlet but instead uses an add-AvailabilityAddressSpace cmdlet @@ -282,7 +272,7 @@ function Set-TargetResource -Source $MyInvocation.MyCommand.ModuleName } } - elseif (('Present' -eq $Ensure ) -and ($Null -ne $AvailabilityAddressSpace)) + elseif ('Present' -eq $Ensure -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Setting AvailabilityAddressSpace $($Identity) with values: $(Convert-M365DscHashtableToString -Hashtable $AvailabilityAddressSpaceParams)" # AvailabilityAddressSpace is a special case in that it does not have a "set-AvailabilityAddressSpace" cmdlet. To change values of an existing AvailabilityAddressSpace it must be removed and then added again with add-AvailabilityAddressSpace @@ -301,7 +291,7 @@ function Set-TargetResource { $AvailabilityAddressSpaceParams.Remove('Identity') | Out-Null $AvailabilityAddressSpaceParams.Remove('Credentials') | Out-Null - add-AvailabilityAddressSpace @AvailabilityAddressSpaceParams -ea stop + Add-AvailabilityAddressSpace @AvailabilityAddressSpaceParams -ea stop } catch { @@ -310,7 +300,7 @@ function Set-TargetResource -Source $MyInvocation.MyCommand.ModuleName } } - elseif (('Absent' -eq $Ensure ) -and ($null -ne $AvailabilityAddressSpace)) + elseif ('Absent' -eq $Ensure -and $currentInstance.Ensure -eq 'Present') { Write-Verbose -Message "Removing AvailabilityAddressSpace $($Identity)" try diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGlobalAddressList/MSFT_EXOGlobalAddressList.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGlobalAddressList/MSFT_EXOGlobalAddressList.psm1 index cde0a678b5..7d506a2fe0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGlobalAddressList/MSFT_EXOGlobalAddressList.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGlobalAddressList/MSFT_EXOGlobalAddressList.psm1 @@ -411,9 +411,13 @@ function Set-TargetResource ConditionalCustomAttribute9 = $ConditionalCustomAttribute9 ConditionalDepartment = $ConditionalDepartment ConditionalStateOrProvince = $ConditionalStateOrProvince - IncludedRecipients = $IncludedRecipients Confirm = $false } + + if (-not [System.String]::IsNullOrEmpty($IncludedRecipients)) + { + $NewGlobalAddressListParams.Add('IncludedRecipients', $IncludedRecipients) + } } $SetGlobalAddressListParams = @{ @@ -437,11 +441,19 @@ function Set-TargetResource ConditionalCustomAttribute9 = $ConditionalCustomAttribute9 ConditionalDepartment = $ConditionalDepartment ConditionalStateOrProvince = $ConditionalStateOrProvince - IncludedRecipients = $IncludedRecipients - RecipientFilter = $RecipientFilter Confirm = $false } + if (-not [System.String]::IsNullOrEmpty($IncludedRecipients)) + { + $SetGlobalAddressListParams.Add('IncludedRecipients', $IncludedRecipients) + } + + if (-not [System.String]::IsNullOrEmpty($RecipientFilter)) + { + $SetGlobalAddressListParams.Add('RecipientFilter', $RecipientFilter) + } + # CASE: Global Address List doesn't exist but should; if ($Ensure -eq 'Present' -and $currentGlobalAddressListConfig.Ensure -eq 'Absent') { diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 deleted file mode 100644 index 68e77e5d2b..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 +++ /dev/null @@ -1,21 +0,0 @@ -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - $Domain = $Credscredential.Username.Split('@')[1] - node localhost - { - EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' - { - UserName = "AdeleV@$Domain" - AuthenticationPolicyName = "Test Policy" # Updaqted Property - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOCASMailboxSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOCASMailboxSettings/2-Update.ps1 index 910c0a15a4..6bf76b701e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOCASMailboxSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOCASMailboxSettings/2-Update.ps1 @@ -14,6 +14,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOCASMailboxSettings 'AdeleVCasMailboxSettings' @@ -22,10 +23,10 @@ Configuration Example ActiveSyncBlockedDeviceIDs = @() ActiveSyncDebugLogging = $False ActiveSyncEnabled = $True - ActiveSyncMailboxPolicy = 'Demo EXO Mobile Device Policy Default' + ActiveSyncMailboxPolicy = 'Default' ActiveSyncSuppressReadReceipt = $False EwsEnabled = $True - Identity = 'AdeleV' + Identity = "admin@$Domain" ImapEnabled = $True # Updated Property ImapForceICalForCalendarRetrievalOption = $False ImapMessagesRetrievalMimeFormat = 'BestBodyFormat' @@ -36,7 +37,7 @@ Configuration Example OutlookMobileEnabled = $True OWAEnabled = $True OWAforDevicesEnabled = $True - OwaMailboxPolicy = 'OwaMailboxPolicy-Default' + OwaMailboxPolicy = 'OwaMailboxPolicy-Integration' PopEnabled = $False PopForceICalForCalendarRetrievalOption = $True PopMessagesRetrievalMimeFormat = 'BestBodyFormat' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOCalendarProcessing/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOCalendarProcessing/2-Update.ps1 index 84ae10d81a..9588fd7db3 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOCalendarProcessing/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOCalendarProcessing/2-Update.ps1 @@ -42,7 +42,7 @@ Configuration Example EnforceSchedulingHorizon = $True; Ensure = "Present"; ForwardRequestsToDelegates = $True; - Identity = "AdeleV"; + Identity = "admin@$Domain"; MaximumConflictInstances = 0; MaximumDurationInMinutes = 1440; MinimumDurationInMinutes = 0; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailAddressPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailAddressPolicy/2-Update.ps1 index 59a62ba67e..3b02fb5f8a 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOEmailAddressPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOEmailAddressPolicy/2-Update.ps1 @@ -20,8 +20,8 @@ Configuration Example Name = "Integration Policy" EnabledEmailAddressTemplates = @("SMTP:@$Domain") EnabledPrimarySMTPAddressTemplate = "@$Domain" - ManagedByFilter = "" - Priority = 2 # Updated Property + ManagedByFilter = "Department -eq 'Sales'" # Updated Property + Priority = 1 Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 4b432876d5..1c757184f2 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-01-25 +# Generated on: 2024-02-01 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.124.1' + ModuleVersion = '1.24.131.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -66,19 +66,19 @@ # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess NestedModules = @( - 'modules\M365DSCAgent.psm1', - 'modules\M365DSCDocGenerator.psm1', - 'modules\M365DSCErrorHandler.psm1', - 'modules\M365DSCLogEngine.psm1', - 'modules\M365DSCPermissions.psm1', - 'modules\M365DSCReport.psm1', - 'modules\M365DSCReverse.psm1', - 'modules\M365DSCStubsUtility.psm1', - 'modules\M365DSCTelemetryEngine.psm1', - 'modules\M365DSCUtil.psm1', - 'modules\M365DSCDRGUtil.psm1', - 'modules\EncodingHelpers\M365DSCEmojis.psm1', - 'modules\EncodingHelpers\M365DSCStringEncoding.psm1' + 'Modules/M365DSCAgent.psm1', + 'Modules/M365DSCDocGenerator.psm1', + 'Modules/M365DSCErrorHandler.psm1', + 'Modules/M365DSCLogEngine.psm1', + 'Modules/M365DSCPermissions.psm1', + 'Modules/M365DSCReport.psm1', + 'Modules/M365DSCReverse.psm1', + 'Modules/M365DSCStubsUtility.psm1', + 'Modules/M365DSCTelemetryEngine.psm1', + 'Modules/M365DSCUtil.psm1', + 'Modules/M365DSCDRGUtil.psm1', + 'Modules/EncodingHelpers/M365DSCEmojis.psm1', + 'Modules/EncodingHelpers/M365DSCStringEncoding.psm1' ) # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. @@ -140,90 +140,34 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* AADAuthenticationMethodPolicyAuthenticator - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicyEmail - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicyFido2 - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicySms - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicySoftware - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicyTemporary - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicyVoice - * Remove the logic path to create a new instance in favor of the update flow. - * AADAuthenticationMethodPolicyX509 - * Remove the logic path to create a new instance in favor of the update flow. - * AADConditionalAccessPolicy - * Fix issue when not all parameters are specified - FIXES [[#4202](https://github.com/microsoft/Microsoft365DSC/issues/4202)] - * AADCrossTenantAccessPolicy - * Removed the ability to specify a value of Absent for the Ensure property. - * AADCrossTenantAccessPolicyCOnfigurationDefault - * Removed the ability to specify a value of Absent for the Ensure property. - * AADGroup - * Changed Set logic to restore groups from the deleted list if a match by - DisplayName is found. - * EXOActiveSyncDeviceAccessRule - * Changed the way Identity is determined by using a combination of the - QueryString and Characteristic parameters. - * EXOAddressList - * Fixed an issue trying to create a new instance when DisplayName is empty. - * EXOApplicationAccessPolicy - * Changed the logic to retrieve existing instances based on Scope. - * EXODataClassification - * DEPRECATED Resource. - * SCAutoSensitivityLabelRule - * Correct export indentation, which caused an issue with report conversion to JSON. - FIXES [[#4240](https://github.com/microsoft/Microsoft365DSC/issues/4240)] - * SPOSharingSettings - * Fixed an Issue where the MySiteSharingCapability could be returned as an - empty string instead of a null value from the Get method. - * TeamsAppPermissionPolicy, TeamsAppSetupPolicy, TeamsCallHoldPolicy, - TeamsIPPhonePolicy, TeamsMobilityPolicy, TeamsNetworkRoamingPolicy, - TeamsShiftsPolicy, TeamsTenantNetworkRegion, TeamsTenantNetworkSite, - TeamsTenantNetworkSubnet, TeamsTenantTrustedIPAddress, TeamsTranslationRule, - TeamsUnassignedNumberTreatment, TeamsVdiPolicy, TeamsWorkloadPolicy - * Fix condition when resource is absent - FIXES [#4227](https://github.com/microsoft/Microsoft365DSC/issues/4227) - * TeamsAudioConferencingPolicy - * Fix condition in Test-TargetResource when resource is absent - FIXES [#4215](https://github.com/microsoft/Microsoft365DSC/issues/4215) - * TeamsCallParkPolicy - * Fix condition in Test-TargetResource when resource is absent - FIXES [#4210](https://github.com/microsoft/Microsoft365DSC/issues/4210) - * TeamsComplianceRecordingPolicy - * Fix condition in Test-TargetResource when resource is absent - FIXES [#4212](https://github.com/microsoft/Microsoft365DSC/issues/4212) - * TeamsCortanaPolicy - * Fix condition in Test-TargetResource when resource is absent - FIXES [#4208](https://github.com/microsoft/Microsoft365DSC/issues/4208) - * TeamsEnhancedEncryptionPolicy - * Fix condition when resource is absent - FIXES [#4221](https://github.com/microsoft/Microsoft365DSC/issues/4221) - * TeamsEventsPolicy - * Add missing attributes - FIXES [#4242](https://github.com/microsoft/Microsoft365DSC/issues/4242) - * TeamsFeedbackPolicy - * Fix condition when resource is absent - FIXES [#4223](https://github.com/microsoft/Microsoft365DSC/issues/4223) - * TeamsFilesPolicy - * Fix condition when resource is absent - FIXES [#4225](https://github.com/microsoft/Microsoft365DSC/issues/4225) - * TeamsGroupPolicyAssignment - * Ensure assignment can still be created if GroupId is not found by trying to - search by DisplayName afterwards - FIXES [#4248](https://github.com/microsoft/Microsoft365DSC/issues/4248) - * TeamsMeetingBroadcastPolicy + ReleaseNotes = '* EXOAvailabilityAddressSpace + * Added support for the TargetServiceEpr and TargetTenantId parameters. + * Fixed the logic to retrieve existing instance by Forest Name. + * EXODistributionGroup + * The Get function now retrieves the ModeratedBy and ManagedBy properties + by the users' UPN instead of their GUID. + * EXOHostedContentFilterRule + * Changed logic to retrieve the Rules by name. Using the Policy's name instead. + * EXOIntraOrganizationConnector + * Fixes the DiscoveryEndpoint value from the Get method to include trailing + forward slash. + * EXOMalwareFilterRule + * Fixed an issue retrieving the right value for the Enabled property + * EXOOMEConfiguration + * Fixes an error in the Get method where the ExternalMailExpiryInDays property + wasnt properly returned. + * EXOSafeLinksPolicy + * Deprecated the UseTranslatedNotificationText property + * TeamsEmergencyCallRoutingPolicy * Fix deletion of resource - FIXES [#4231](https://github.com/microsoft/Microsoft365DSC/issues/4231) - * TeamsMobilityPolicy - * Validate string set on parameter MobileDialerPreference + FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) + * TEAMS + * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES - * Updated Microsoft.Graph dependencies to version 2.12.0. - * Updated MicrosoftTeams dependencies to version 5.9.0.' + * Updated MSCloudLoginAssistant dependencies to version 1.1.10. + * MISC + * Change the way to Export encoding is done so that it no longer relies + on the Get-DSCResource function.' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false diff --git a/Modules/Microsoft365DSC/Modules/EncodingHelpers/M365DSCStringEncoding.psm1 b/Modules/Microsoft365DSC/Modules/EncodingHelpers/M365DSCStringEncoding.psm1 index e668fbb411..3d1ddc9224 100644 --- a/Modules/Microsoft365DSC/Modules/EncodingHelpers/M365DSCStringEncoding.psm1 +++ b/Modules/Microsoft365DSC/Modules/EncodingHelpers/M365DSCStringEncoding.psm1 @@ -42,9 +42,12 @@ function Format-M365DSCString # Cache the DSC resource to a script-scope variable. # This avoids fetching the definition multiple times for the same resource, increasing overall speed. - if (-not ($DSCResource.Name -eq $ResourceName)) { - $Script:DSCResource = Get-DscResource -Module 'Microsoft365DSC' -Name $ResourceName - } + $ResourcePath = Join-Path -Path $PSScriptRoot ` + -ChildPath "../../DSCResources/MSFT_$ResourceName/MSFT_$ResourceName.psm1" ` + -Resolve + + Import-Module $ResourcePath + $commandInfo = Get-Command -Module "MSFT_$ResourceName" | Where-Object -FilterScript {$_.Name -eq 'Get-TargetResource'} # For each invalid character, look for an instance in the string, # if an instance is found, @@ -56,14 +59,13 @@ function Format-M365DSCString $newProperties.$key.GetType().ToString() -eq 'System.String') { # Obtain the type for this property from the module; - $foundProperty = $DSCResource.Properties | Where-Object -FilterScript { $_.Name -eq $key } foreach ($entry in $InvalidCharacters) { - if ($foundProperty.PropertyType -eq '[string]') + if ($commandInfo.$key.ParameterType -eq 'String') { $newProperties.$key = $newProperties.$key.Replace($entry.InvalidCharacter.ToString(), $entry.MainReplaceBy.ToString()) } - elseif ($foundProperty.PropertyType -like '`[MSFT_*`]') + elseif ($foundProperty.PropertyType -like "CIMInstance*") { # Case property is a CIMInstance $newProperties.$key = $newProperties.$key.Replace($entry.InvalidCharacter.ToString(), $entry.CimReplaceBy.ToString()) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCErrorHandler.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCErrorHandler.psm1 index dbc985f6f5..de7422a510 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCErrorHandler.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCErrorHandler.psm1 @@ -19,8 +19,11 @@ function Save-M365DSCPartialExport $FileName ) - $tempPath = Join-Path -Path $env:TEMP -ChildPath $FileName - $Content | Out-File -FilePath $tempPath -Append:$true -Force + if (-not [System.String]::IsNullOrEmpty($env:Temp)) + { + $tempPath = Join-Path -Path $env:TEMP -ChildPath $FileName + $Content | Out-File -FilePath $tempPath -Append:$true -Force + } } Export-ModuleMember -Function @( diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 index f9e589b770..3f5af826af 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReverse.psm1 @@ -95,6 +95,7 @@ function Start-M365DSCConfigurationExtract # PowerShell Gallery try { + Write-Verbose -Message 'Testing Module Validity' Test-M365DSCModuleValidity } catch @@ -111,6 +112,7 @@ function Start-M365DSCConfigurationExtract if ($null -ne $Workloads) { + Write-Verbose -Message 'Retrieving the resources to export by workloads' $Components = Get-M365DSCResourcesByWorkloads -Workloads $Workloads ` -Mode $Mode } @@ -189,6 +191,7 @@ function Start-M365DSCConfigurationExtract # received, write a warning. if ($Components.Length -eq 0) { + Write-Verbose -Message 'Retrieving all resources' $allResourcesInModule = Get-M365DSCAllResources $selectedItems = Compare-Object -ReferenceObject $allResourcesInModule ` -DifferenceObject $ComponentsToSkip | Where-Object -FilterScript { $_.SideIndicator -eq '<=' } @@ -203,6 +206,7 @@ function Start-M365DSCConfigurationExtract $selectedResources = $Components } + Write-Verbose -Message 'Based on provided parameters, retrieving the most secure authentication method to use.' $allSupportedResourcesWithMostSecureAuthMethod = Get-M365DSCComponentsWithMostSecureAuthenticationType -AuthenticationMethod $AuthMethods ` -Resources $selectedResources @@ -272,6 +276,7 @@ function Start-M365DSCConfigurationExtract { if ($null -ne $Credential -and $Credential.UserName.Contains('@')) { + Write-Verbose -Message "Retrieving organization name based on provided credentials." $organization = $Credential.UserName.Split('@')[1] } } @@ -443,6 +448,7 @@ function Start-M365DSCConfigurationExtract $newline = $true # Add the Credential to the Credentials List + Write-Verbose -Message 'Adding the provided credentials to the list of variables' Save-Credentials -UserName 'credential' } 'ManagedIdentity' @@ -470,14 +476,17 @@ function Start-M365DSCConfigurationExtract $DSCContent.Append(" Node localhost`r`n") | Out-Null $DSCContent.Append(" {`r`n") | Out-Null + Write-Verbose -Message 'Adding initial entry in the ConfigurationData file.' Add-ConfigurationDataEntry -Node 'localhost' ` -Key 'ServerNumber' ` -Value '0' ` -Description 'Default Value Used to Ensure a Configuration Data File is Generated' + Write-Verbose -Message 'Retrieving resources path' $ResourcesPath = Join-Path -Path $PSScriptRoot ` - -ChildPath '..\DSCResources\' ` + -ChildPath '../DSCResources/' ` -Resolve + Write-Verbose -Message 'Loop through all resources files.' $AllResources = Get-ChildItem $ResourcesPath -Recurse | Where-Object { $_.Name -like 'MSFT_*.psm1' } $i = 1 @@ -550,6 +559,7 @@ function Start-M365DSCConfigurationExtract } } + $ResourcesPath = $ResourcesPath | Sort-Object $_.Name foreach ($resource in $ResourcesPath) { $resourceName = $resource.Name.Split('.')[0] -replace 'MSFT_', '' @@ -801,9 +811,12 @@ function Start-M365DSCConfigurationExtract { foreach ($fileToCopy in $filesToDownload) { - $filePath = Join-Path $env:Temp $fileToCopy.Name -Resolve - $destPath = Join-Path $OutputDSCPath $fileToCopy.Name - Copy-Item -Path $filePath -Destination $destPath + if (-not [System.String]::IsNullOrEmpty($env:Temp)) + { + $filePath = Join-Path $env:Temp $fileToCopy.Name -Resolve + $destPath = Join-Path $OutputDSCPath $fileToCopy.Name + Copy-Item -Path $filePath -Destination $destPath + } } } } @@ -824,44 +837,51 @@ function Start-M365DSCConfigurationExtract if (!$AzureAutomation -and !$ManagedIdentity.IsPresent) { - if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) + try { - $LCMConfig = Get-DscLocalConfigurationManager - if ($null -ne $LCMConfig.CertificateID) + if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { - try + $LCMConfig = Get-DscLocalConfigurationManager + if ($null -ne $LCMConfig.CertificateID) { - # Export the certificate assigned to the LCM - $certPath = $OutputDSCPath + 'M365DSC.cer' - if (Test-Path $certPath) + try { - Remove-Item $certPath -Force + # Export the certificate assigned to the LCM + $certPath = $OutputDSCPath + 'M365DSC.cer' + if (Test-Path $certPath) + { + Remove-Item $certPath -Force + } + Export-Certificate -FilePath $certPath ` + -Cert "cert:\LocalMachine\my\$($LCMConfig.CertificateID)" ` + -Type CERT ` + -NoClobber | Out-Null + } + catch + { + New-M365DSCLogEntry -Message 'Error while exporting the DSC certificate:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential } - Export-Certificate -FilePath $certPath ` - -Cert "cert:\LocalMachine\my\$($LCMConfig.CertificateID)" ` - -Type CERT ` - -NoClobber | Out-Null - } - catch - { - New-M365DSCLogEntry -Message 'Error while exporting the DSC certificate:' ` - -Exception $_ ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - Add-ConfigurationDataEntry -Node 'localhost' ` - -Key 'CertificateFile' ` - -Value 'M365DSC.cer' ` - -Description 'Path of the certificate used to encrypt credentials in the file.' + Add-ConfigurationDataEntry -Node 'localhost' ` + -Key 'CertificateFile' ` + -Value 'M365DSC.cer' ` + -Description 'Path of the certificate used to encrypt credentials in the file.' + } + } + else + { + Write-Host "$($Global:M365DSCEmojiYellowCircle) Warning {" -NoNewline + Write-Host "Cannot export Local Configuration Manager settings. This process isn't executed with Administrative Privileges!" -NoNewline -ForegroundColor DarkCyan + Write-Host '}' } } - else + catch { - Write-Host "$($Global:M365DSCEmojiYellowCircle) Warning {" -NoNewline - Write-Host "Cannot export Local Configuration Manager settings. This process isn't executed with Administrative Privileges!" -NoNewline -ForegroundColor DarkCyan - Write-Host '}' + Write-Verbose -Message "Could not retrieve current Windows Principal. This may be due to the fact that the current OS is not Windows." } } $outputConfigurationData = $OutputDSCPath + 'ConfigurationData.psd1' @@ -880,8 +900,11 @@ function Start-M365DSCConfigurationExtract } catch { - $partialPath = Join-Path $env:TEMP -ChildPath "$($Global:PartialExportFileName)" - Write-Host "Partial Export file was saved at: $partialPath" + if (-not [System.String]::IsNullOrEmpty($env:Temp)) + { + $partialPath = Join-Path $env:TEMP -ChildPath "$($Global:PartialExportFileName)" + Write-Host "Partial Export file was saved at: $partialPath" + } throw $_ } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 168b0fc893..f9d9554dd2 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -12,7 +12,7 @@ function Get-ApplicationInsightsTelemetryClient if ($null -eq $Global:M365DSCTelemetryEngine) { - $AI = "$PSScriptRoot\..\Dependencies\Microsoft.ApplicationInsights.dll" + $AI = "$PSScriptRoot/../Dependencies/Microsoft.ApplicationInsights.dll" [Reflection.Assembly]::LoadFile($AI) | Out-Null $InstrumentationKey = [System.Environment]::GetEnvironmentVariable('M365DSCTelemetryInstrumentationKey', ` @@ -192,7 +192,7 @@ function Add-M365DSCTelemetryEvent # Get Dependencies loaded versions try { - $currentPath = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve + $currentPath = Join-Path -Path $PSScriptRoot -ChildPath '../' -Resolve $manifest = Import-PowerShellDataFile "$currentPath/Microsoft365DSC.psd1" $dependencies = $manifest.RequiredModules diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9f10e145ac..aca92258d4 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -2748,7 +2748,7 @@ function Update-M365DSCDependencies $Global:MaximumFunctionCount = 32767 $InformationPreference = 'Continue' - $currentPath = Join-Path -Path $PSScriptRoot -ChildPath '..\' -Resolve + $currentPath = Join-Path -Path $PSScriptRoot -ChildPath '../' -Resolve $manifest = Import-PowerShellDataFile "$currentPath/Dependencies/Manifest.psd1" $dependencies = $manifest.Dependencies $i = 1 @@ -2767,11 +2767,20 @@ function Update-M365DSCDependencies if ((-not $found -or $Force) -and -not $ValidateOnly) { - if ((-not(([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))) -and ($Scope -eq "AllUsers")) + $errorFound = $false + try + { + if ((-not(([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))) -and ($Scope -eq "AllUsers")) + { + Write-Error 'Cannot update the dependencies for Microsoft365DSC. You need to run this command as a local administrator.' + $errorFound = $true + } + } + catch { - Write-Error 'Cannot update the dependencies for Microsoft365DSC. You need to run this command as a local administrator.' + Write-Verbose -Message "Couldn't retrieve Windows Principal. One possible cause is that the current environment is not Windows OS." } - else + if (-not $errorFound) { Write-Information -MessageData "Installing $($dependency.ModuleName) version {$($dependency.RequiredVersion)}" Remove-Module $dependency.ModuleName -Force -ErrorAction SilentlyContinue From b895da762bfe4f8a3bd71cedc3c4327068b843c3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 1 Feb 2024 19:40:29 -0500 Subject: [PATCH 066/171] Update Microsoft365DSC.psd1 --- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 1c757184f2..4ded070db3 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -145,9 +145,9 @@ * Fixed the logic to retrieve existing instance by Forest Name. * EXODistributionGroup * The Get function now retrieves the ModeratedBy and ManagedBy properties - by the users' UPN instead of their GUID. + by the users UPN instead of their GUID. * EXOHostedContentFilterRule - * Changed logic to retrieve the Rules by name. Using the Policy's name instead. + * Changed logic to retrieve the Rules by name. Using the Policys name instead. * EXOIntraOrganizationConnector * Fixes the DiscoveryEndpoint value from the Get method to include trailing forward slash. From 5b403376801c279a9bb449bdee161a8e2c8cc49f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 1 Feb 2024 19:56:50 -0500 Subject: [PATCH 067/171] Fixes Unit Tests --- .../MSFT_EXOAcceptedDomain.psm1 | 2 +- .../Microsoft365DSC.EXOAcceptedDomain.Tests.ps1 | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 index 53797d3961..a5a1401f1e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAcceptedDomain/MSFT_EXOAcceptedDomain.psm1 @@ -87,7 +87,7 @@ function Get-TargetResource try { Write-Verbose -Message 'Getting all Accepted Domain' - $AllAcceptedDomain = Get-AcceptedDomain -Identity $Identity -ErrorAction SilentlyContinue + $AcceptedDomain = Get-AcceptedDomain -Identity $Identity -ErrorAction SilentlyContinue if ($null -eq $AcceptedDomain) { diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAcceptedDomain.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAcceptedDomain.Tests.ps1 index 4cf3d643ae..f09e2bc4fb 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAcceptedDomain.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAcceptedDomain.Tests.ps1 @@ -51,12 +51,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Identity = 'contoso.com' } Mock -CommandName Get-AcceptedDomain -MockWith { - return @{ - DomainType = 'Authoritative' - Identity = 'different.contoso.com' - MatchSubDomains = $false - OutboundOnly = $false - } + return $null } Mock -CommandName Set-AcceptedDomain -MockWith { return @{ @@ -93,12 +88,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-AcceptedDomain -MockWith { - return @{ - DomainType = 'Authoritative' - Identity = 'different.tailspin.com' - MatchSubDomains = $false - OutboundOnly = $false - } + return $null } } From a7bc2dc0116e5a970449b957b7d14d294fc81e6c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 07:08:23 -0500 Subject: [PATCH 068/171] Release 1.24.131.2 --- CHANGELOG.md | 7 +++++ .../MSFT_TeamsMeetingPolicy.psm1 | 27 ++++++++++++++++--- .../MSFT_TeamsUpdateManagementPolicy.psm1 | 6 ++++- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 8 ++++-- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c40168611..ced60757cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# 1.24.131.2 + +* TeamsMeetingPolicy + * Fixed issue with missing ManagedIdentity parameter in Test signature. +* TeamsUpdateManagementPolicy + * Fixed issue with missing ManagedIdentity parameter in Test signature. + # 1.24.131.1 * EXOAvailabilityAddressSpace diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 index 197912037e..494656a498 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 @@ -295,7 +295,11 @@ function Get-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message "Getting the Teams Meeting Policy $($Identity)" @@ -396,6 +400,7 @@ function Get-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } } catch @@ -706,7 +711,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) Write-Verbose -Message 'Setting Teams Meeting Policy' @@ -734,6 +743,7 @@ function Set-TargetResource $SetParameters.Remove('ApplicationId') | Out-Null $SetParameters.Remove('TenantId') | Out-Null $SetParameters.Remove('CertificateThumbprint') | Out-Null + $SetParameters.Remove('ManagedIdentity') | Out-Null $SetParameters.Remove('Verbose') | Out-Null # Needs to be implicitly removed for the cmdlet to work if ($Ensure -eq 'Present' -and $CurrentValues.Ensure -eq 'Absent') @@ -1074,7 +1084,11 @@ function Test-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -1134,7 +1148,11 @@ function Export-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftTeams' ` -InboundParameters $PSBoundParameters @@ -1166,6 +1184,7 @@ function Export-TargetResource ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent } $Results = Get-TargetResource @Params $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpdateManagementPolicy/MSFT_TeamsUpdateManagementPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpdateManagementPolicy/MSFT_TeamsUpdateManagementPolicy.psm1 index 01388d09ad..7f795ddcb8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpdateManagementPolicy/MSFT_TeamsUpdateManagementPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsUpdateManagementPolicy/MSFT_TeamsUpdateManagementPolicy.psm1 @@ -197,7 +197,11 @@ function Set-TargetResource [Parameter()] [System.String] - $CertificateThumbprint + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity ) #Ensure the proper dependencies are installed in the current environment. diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 4ded070db3..8c1d7b4685 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-01 +# Generated on: 2024-02-02 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.131.1' + ModuleVersion = '1.24.131.2' # Supported PSEditions # CompatiblePSEditions = @() @@ -161,6 +161,10 @@ * TeamsEmergencyCallRoutingPolicy * Fix deletion of resource FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) + * TeamsMeetingPolicy + * Fixed issue with missing ManagedIdentity parameter in Test signature. + * TeamsUpdateManagementPolicy + * Fixed issue with missing ManagedIdentity parameter in Test signature. * TEAMS * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES From 1d57cd98f9afe8b478eb8fda7d00538002234734 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 07:09:40 -0500 Subject: [PATCH 069/171] Updates --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ced60757cc..af75d9bbd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ * TeamsMeetingPolicy * Fixed issue with missing ManagedIdentity parameter in Test signature. * TeamsUpdateManagementPolicy - * Fixed issue with missing ManagedIdentity parameter in Test signature. + * Fixed issue with missing ManagedIdentity parameter in Set signature. # 1.24.131.1 diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 8c1d7b4685..bd1c11a715 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -164,7 +164,7 @@ * TeamsMeetingPolicy * Fixed issue with missing ManagedIdentity parameter in Test signature. * TeamsUpdateManagementPolicy - * Fixed issue with missing ManagedIdentity parameter in Test signature. + * Fixed issue with missing ManagedIdentity parameter in Set signature. * TEAMS * Added support for ManagedIdentity Authentication across Teams resources. * DEPENDENCIES From d327fcd3af372081f20fc64673d0a95dd3fb1ec3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 11:08:33 -0500 Subject: [PATCH 070/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOGroupSettings/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 index a7b38e6fd1..045eb6b219 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 @@ -19,7 +19,7 @@ Configuration Example { EXOGroupSettings 'TestGroup' { - DisplayName = "Test Group"; + DisplayName = "DemoDG"; AccessType = "Public"; AlwaysSubscribeMembersToCalendarEvents = $False; AuditLogAgeLimit = "90.00:00:00"; From 012ce10bfc535ee570576f338fe22628facecfe5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 11:37:32 -0500 Subject: [PATCH 071/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOGroupSettings/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 index 045eb6b219..ee0f24fd92 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOGroupSettings/2-Update.ps1 @@ -19,7 +19,7 @@ Configuration Example { EXOGroupSettings 'TestGroup' { - DisplayName = "DemoDG"; + DisplayName = "All Company"; AccessType = "Public"; AlwaysSubscribeMembersToCalendarEvents = $False; AuditLogAgeLimit = "90.00:00:00"; From ef9f1a58cb040efabb571e2c3e8a630b30291e27 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 13:20:24 -0500 Subject: [PATCH 072/171] Update 2-Update.ps1 --- .../Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 index 3fb5e18e6a..5ee8ed475d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 @@ -27,7 +27,7 @@ Configuration Example EndTime = "1/23/2024 3:00:00 PM"; Ensure = "Present"; ExternalAudience = "All"; - ExternalMessage = ""; + ExternalMessage = (New-Guid).ToString(); # Updated Property Identity = "AdeleV@$Domain"; InternalMessage = ""; OOFEventSubject = ""; From 74dc3065c80d238237a133e388d12fe008d673fb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 13:28:09 -0500 Subject: [PATCH 073/171] Update 2-Update.ps1 --- .../Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 index 5ee8ed475d..6dfcc36565 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxAutoReplyConfiguration/2-Update.ps1 @@ -22,7 +22,7 @@ Configuration Example CreateOOFEvent = $False; Credential = $Credscredential; DeclineAllEventsForScheduledOOF = $False; - DeclineEventsForScheduledOOF = $True; # Updated Property + DeclineEventsForScheduledOOF = $False; DeclineMeetingMessage = ""; EndTime = "1/23/2024 3:00:00 PM"; Ensure = "Present"; From 8f6a727c9a4f87b3e7a960da683f781bbdc994bb Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 13:51:09 -0500 Subject: [PATCH 074/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 index 12a8ee1f95..13893f2685 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 @@ -13,6 +13,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOMailboxCalendarFolder "JohnCalendarFolder" @@ -20,7 +21,7 @@ Configuration Example Credential = $credsCredential; DetailLevel = "AvailabilityOnly"; Ensure = "Present"; - Identity = "AdeleV:\Calendar"; + Identity = "AdeleV@$Domain:\Calendar"; PublishDateRangeFrom = "ThreeMonths"; PublishDateRangeTo = "ThreeMonths"; PublishEnabled = $True; # Updated Property From 4252396cc3542685f942e9431c4f19d4e2785ec1 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 13:58:47 -0500 Subject: [PATCH 075/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 index 13893f2685..1a92dcadf8 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 @@ -21,7 +21,7 @@ Configuration Example Credential = $credsCredential; DetailLevel = "AvailabilityOnly"; Ensure = "Present"; - Identity = "AdeleV@$Domain:\Calendar"; + Identity = "AdeleV@$Domain" + ":\Calendar"; PublishDateRangeFrom = "ThreeMonths"; PublishDateRangeTo = "ThreeMonths"; PublishEnabled = $True; # Updated Property From 222bf6ee9853334d92bf1efb5b8dedd6fe3e6f50 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 14:08:02 -0500 Subject: [PATCH 076/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 index 1a92dcadf8..d634a068e6 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxCalendarFolder/2-Update.ps1 @@ -21,7 +21,7 @@ Configuration Example Credential = $credsCredential; DetailLevel = "AvailabilityOnly"; Ensure = "Present"; - Identity = "AdeleV@$Domain" + ":\Calendar"; + Identity = "AlexW@$Domain" + ":\Calendar"; PublishDateRangeFrom = "ThreeMonths"; PublishDateRangeTo = "ThreeMonths"; PublishEnabled = $True; # Updated Property From 005a07024456a7c8f1eb6045fdf223d5dd43c28d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 2 Feb 2024 14:15:02 -0500 Subject: [PATCH 077/171] Update 2-Update.ps1 --- .../Examples/Resources/EXOMailboxPermission/2-Update.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPermission/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPermission/2-Update.ps1 index 732a1e769d..61c3877d25 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPermission/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPermission/2-Update.ps1 @@ -12,6 +12,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOMailboxPermission "TestPermission" @@ -20,7 +21,7 @@ Configuration Example Credential = $credsCredential; Deny = $True; # Updated Property Ensure = "Present"; - Identity = "AdeleV"; + Identity = "AlexW@$Domain"; InheritanceType = "All"; User = "NT AUTHORITY\SELF"; } From 342d577f528d246a24aabb747a8e72e04a0f1c92 Mon Sep 17 00:00:00 2001 From: Tayhall <4ndrewhall@gmail.com> Date: Mon, 5 Feb 2024 17:29:56 +0000 Subject: [PATCH 078/171] First commit DLPCompliance params --- .../MSFT_SCDLPComplianceRule.psm1 | 521 ++++++++++++++++-- .../MSFT_SCDLPComplianceRule.schema.mof | 33 ++ .../SCDLPComplianceRule.md | 34 +- 3 files changed, 545 insertions(+), 43 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 index 981dd8ac89..6e2493dbc6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 @@ -138,10 +138,144 @@ function Get-TargetResource [System.Boolean] $DocumentIsPasswordProtected, - [Parameter()] + [Parameter()] [System.Boolean] $ExceptIfDocumentIsPasswordProtected, + [Parameter()] + [System.String[]] + $MessageTypeMatches, + + [Parameter()] + [System.String[]] + $ExceptIfMessageTypeMatches, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $FromScope, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $ExceptIfFromScope, + + [Parameter()] + [System.String[]] + $SubjectContainsWords, + + [Parameter()] + [System.String[]] + $SubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $SubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $SubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $ContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfContentPropertyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $FromAddressContainsWords, + + [Parameter()] + [System.String[]] + $FromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderIPRanges, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [System.String[]] + $DocumentContainsWords, + + [Parameter()] + [System.Boolean] + $ContentIsNotLabeled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -231,6 +365,11 @@ function Get-TargetResource $AnyOfRecipientAddressContainsWords = $PolicyRule.AnyOfRecipientAddressContainsWords.Replace(' ', '').Split(',') } + if ($null -ne $PolicyRule.ExceptIfAnyOfRecipientAddressContainsWords -and $PolicyRule.ExceptIfAnyOfRecipientAddressContainsWords.count -gt 0) + { + $ExceptIfAnyOfRecipientAddressContainsWords = $PolicyRule.ExceptIfAnyOfRecipientAddressContainsWords.Replace(' ', '').Split(',') + } + if ($null -ne $PolicyRule.AnyOfRecipientAddressMatchesPatterns -and $PolicyRule.AnyOfRecipientAddressMatchesPatterns -gt 0) { $AnyOfRecipientAddressMatchesPatterns = $PolicyRule.AnyOfRecipientAddressMatchesPatterns.Replace(' ', '').Split(',') @@ -247,46 +386,75 @@ function Get-TargetResource } $result = @{ - Ensure = 'Present' - Name = $PolicyRule.Name - Policy = $PolicyRule.ParentPolicyName - AccessScope = $PolicyRule.AccessScope - BlockAccess = $PolicyRule.BlockAccess - BlockAccessScope = $PolicyRule.BlockAccessScope - Comment = $PolicyRule.Comment - ContentContainsSensitiveInformation = $PolicyRule.ContentContainsSensitiveInformation - ExceptIfContentContainsSensitiveInformation = $PolicyRule.ExceptIfContentContainsSensitiveInformation - ContentPropertyContainsWords = $PolicyRule.ContentPropertyContainsWords - Disabled = $PolicyRule.Disabled - GenerateAlert = $PolicyRule.GenerateAlert - GenerateIncidentReport = $PolicyRule.GenerateIncidentReport - IncidentReportContent = $ArrayIncidentReportContent - NotifyAllowOverride = $NotifyAllowOverrideValue - NotifyEmailCustomText = $PolicyRule.NotifyEmailCustomText - NotifyPolicyTipCustomText = $PolicyRule.NotifyPolicyTipCustomText - NotifyUser = $PolicyRule.NotifyUser - ReportSeverityLevel = $PolicyRule.ReportSeverityLevel - RuleErrorAction = $PolicyRule.RuleErrorAction - RemoveRMSTemplate = $PolicyRule.RemoveRMSTemplate - StopPolicyProcessing = $PolicyRule.StopPolicyProcessing - DocumentIsUnsupported = $PolicyRule.DocumentIsUnsupported - ExceptIfDocumentIsUnsupported = $PolicyRule.ExceptIfDocumentIsUnsupported - HasSenderOverride = $PolicyRule.HasSenderOverride - ExceptIfHasSenderOverride = $PolicyRule.ExceptIfHasSenderOverride - ProcessingLimitExceeded = $PolicyRule.ProcessingLimitExceeded - ExceptIfProcessingLimitExceeded = $PolicyRule.ExceptIfProcessingLimitExceeded - DocumentIsPasswordProtected = $PolicyRule.DocumentIsPasswordProtected - ExceptIfDocumentIsPasswordProtected = $PolicyRule.ExceptIfDocumentIsPasswordProtected - AnyOfRecipientAddressContainsWords = $AnyOfRecipientAddressContainsWords - AnyOfRecipientAddressMatchesPatterns = $AnyOfRecipientAddressMatchesPatterns - ContentExtensionMatchesWords = $ContentExtensionMatchesWords - ExceptIfContentExtensionMatchesWords = $ExceptIfContentExtensionMatchesWords - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - CertificateThumbprint = $CertificateThumbprint - CertificatePath = $CertificatePath - CertificatePassword = $CertificatePassword + Ensure = 'Present' + Name = $PolicyRule.Name + Policy = $PolicyRule.ParentPolicyName + AccessScope = $PolicyRule.AccessScope + BlockAccess = $PolicyRule.BlockAccess + BlockAccessScope = $PolicyRule.BlockAccessScope + Comment = $PolicyRule.Comment + ContentContainsSensitiveInformation = $PolicyRule.ContentContainsSensitiveInformation + ExceptIfContentContainsSensitiveInformation = $PolicyRule.ExceptIfContentContainsSensitiveInformation + ContentPropertyContainsWords = $PolicyRule.ContentPropertyContainsWords + Disabled = $PolicyRule.Disabled + GenerateAlert = $PolicyRule.GenerateAlert + GenerateIncidentReport = $PolicyRule.GenerateIncidentReport + IncidentReportContent = $ArrayIncidentReportContent + NotifyAllowOverride = $NotifyAllowOverrideValue + NotifyEmailCustomText = $PolicyRule.NotifyEmailCustomText + NotifyPolicyTipCustomText = $PolicyRule.NotifyPolicyTipCustomText + NotifyUser = $PolicyRule.NotifyUser + ReportSeverityLevel = $PolicyRule.ReportSeverityLevel + RuleErrorAction = $PolicyRule.RuleErrorAction + RemoveRMSTemplate = $PolicyRule.RemoveRMSTemplate + StopPolicyProcessing = $PolicyRule.StopPolicyProcessing + DocumentIsUnsupported = $PolicyRule.DocumentIsUnsupported + ExceptIfDocumentIsUnsupported = $PolicyRule.ExceptIfDocumentIsUnsupported + HasSenderOverride = $PolicyRule.HasSenderOverride + ExceptIfHasSenderOverride = $PolicyRule.ExceptIfHasSenderOverride + ProcessingLimitExceeded = $PolicyRule.ProcessingLimitExceeded + ExceptIfProcessingLimitExceeded = $PolicyRule.ExceptIfProcessingLimitExceeded + DocumentIsPasswordProtected = $PolicyRule.DocumentIsPasswordProtected + ExceptIfDocumentIsPasswordProtected = $PolicyRule.ExceptIfDocumentIsPasswordProtected + MessageTypeMatches = $PolicyRule.MessageTypeMatches + ExceptIfMessageTypeMatches = $PolicyRule.ExceptIfMessageTypeMatches + FromScope = $PolicyRule.FromScope + ExceptIfFromScope = $PolicyRule.ExceptIfFromScope + SubjectContainsWords = $PolicyRule.SubjectContainsWords + SubjectMatchesPatterns = $PolicyRule.SubjectMatchesPatterns + SubjectOrBodyContainsWords = $PolicyRule.SubjectOrBodyContainsWords + SubjectOrBodyMatchesPatterns = $PolicyRule.SubjectOrBodyMatchesPatterns + ContentCharacterSetContainsWords = $PolicyRule.ContentCharacterSetContainsWords + DocumentNameMatchesPatterns = $PolicyRule.DocumentNameMatchesPatterns + DocumentNameMatchesWords = $PolicyRule.DocumentNameMatchesWords + ExceptIfAnyOfRecipientAddressMatchesPatterns = $PolicyRule.ExceptIfAnyOfRecipientAddressMatchesPatterns + ExceptIfContentCharacterSetContainsWords = $PolicyRule.ExceptIfContentCharacterSetContainsWords + ExceptIfContentPropertyContainsWords = $PolicyRule.ExceptIfContentPropertyContainsWords + ExceptIfDocumentNameMatchesPatterns = $PolicyRule.ExceptIfDocumentNameMatchesPatterns + ExceptIfDocumentNameMatchesWords = $PolicyRule.ExceptIfDocumentNameMatchesWords + RecipientDomainIs = $PolicyRule.RecipientDomainIs + ExceptIfRecipientDomainIs = $PolicyRule.ExceptIfRecipientDomainIs + ExceptIfSenderDomainIs = $PolicyRule.ExceptIfSenderDomainIs + ExceptIfSenderIPRanges = $PolicyRule.ExceptIfSenderIPRanges + ExceptIfSentTo = $PolicyRule.ExceptIfSentTo + ExceptIfSubjectContainsWords = $PolicyRule.ExceptIfSubjectContainsWords + ExceptIfSubjectMatchesPatterns = $PolicyRule.ExceptIfSubjectMatchesPatterns + ExceptIfSubjectOrBodyContainsWords = $PolicyRule.ExceptIfSubjectOrBodyContainsWords + ExceptIfSubjectOrBodyMatchesPatterns = $PolicyRule.ExceptIfSubjectOrBodyMatchesPatterns + FromAddressMatchesPatterns = $PolicyRule.FromAddressMatchesPatterns + SentToMemberOf = $PolicyRule.FromAddressMatchesPatterns + DocumentContainsWords = $PolicyRule.DocumentContainsWords + ContentIsNotLabeled = $PolicyRule.ContentIsNotLabeled + AnyOfRecipientAddressContainsWords = $AnyOfRecipientAddressContainsWords + AnyOfRecipientAddressMatchesPatterns = $AnyOfRecipientAddressMatchesPatterns + ContentExtensionMatchesWords = $ContentExtensionMatchesWords + ExceptIfContentExtensionMatchesWords = $ExceptIfContentExtensionMatchesWords + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword } $paramsToRemove = @() @@ -458,10 +626,144 @@ function Set-TargetResource [System.Boolean] $DocumentIsPasswordProtected, - [Parameter()] + [Parameter()] [System.Boolean] $ExceptIfDocumentIsPasswordProtected, + [Parameter()] + [System.String[]] + $MessageTypeMatches, + + [Parameter()] + [System.String[]] + $ExceptIfMessageTypeMatches, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $FromScope, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $ExceptIfFromScope, + + [Parameter()] + [System.String[]] + $SubjectContainsWords, + + [Parameter()] + [System.String[]] + $SubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $SubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $SubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $ContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfContentPropertyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $FromAddressContainsWords, + + [Parameter()] + [System.String[]] + $FromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderIPRanges, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [System.String[]] + $DocumentContainsWords, + + [Parameter()] + [System.Boolean] + $ContentIsNotLabeled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -561,6 +863,7 @@ function Set-TargetResource $CreationParams.Remove('ManagedIdentity') | Out-Null $CreationParams.Remove('ApplicationSecret') | Out-Null + Write-Verbose -Message "Calling New-DLPComplianceRule with Values: $(Convert-M365DscHashtableToString -Hashtable $CreationParams)" New-DLPComplianceRule @CreationParams } @@ -772,6 +1075,140 @@ function Test-TargetResource [System.Boolean] $ExceptIfDocumentIsPasswordProtected, + [Parameter()] + [System.String[]] + $MessageTypeMatches, + + [Parameter()] + [System.String[]] + $ExceptIfMessageTypeMatches, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $FromScope, + + [Parameter()] + [ValidateSet('InOrganization', 'NotInOrganization')] + [System.String[]] + $ExceptIfFromScope, + + [Parameter()] + [System.String[]] + $SubjectContainsWords, + + [Parameter()] + [System.String[]] + $SubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $SubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $SubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $ContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $DocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfAnyOfRecipientAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfContentCharacterSetContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfContentPropertyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfDocumentNameMatchesWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfFromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $FromAddressContainsWords, + + [Parameter()] + [System.String[]] + $FromAddressMatchesPatterns, + + [Parameter()] + [System.String[]] + $RecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfRecipientDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderDomainIs, + + [Parameter()] + [System.String[]] + $ExceptIfSenderIPRanges, + + [Parameter()] + [System.String[]] + $ExceptIfSentTo, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectMatchesPatterns, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyContainsWords, + + [Parameter()] + [System.String[]] + $ExceptIfSubjectOrBodyMatchesPatterns, + + [Parameter()] + [System.String[]] + $SentToMemberOf, + + [Parameter()] + [System.String[]] + $DocumentContainsWords, + + [Parameter()] + [System.Boolean] + $ContentIsNotLabeled, + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof index 851847008e..af95ed23e7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof @@ -72,6 +72,39 @@ class MSFT_SCDLPComplianceRule : OMI_BaseResource [Write, Description("The ExceptIfProcessingLimitExceeded parameter specifies an exception for the DLP rule that looks for files where scanning couldn't complete.")] Boolean ExceptIfProcessingLimitExceeded; [Write, Description("The DocumentIsPasswordProtected parameter specifies a condition for the DLP rule that looks for password protected files (because the contents of the file can't be inspected). Password detection only works for Office documents and .zip files.")] Boolean DocumentIsPasswordProtected; [Write, Description("The ExceptIfDocumentIsPasswordProtected parameter specifies an exception for the DLP rule that looks for password protected files (because the contents of the file can't be inspected). Password detection only works for Office documents and .zip files. ")] Boolean ExceptIfDocumentIsPasswordProtected; + [Write, Description("The MessageTypeMatches parameter specifies a condition for the DLP rule that looks for types of SMIME message patterns.")] String MessageTypeMatches[]; + [Write, Description("The FromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.")] String FromScope[]; + [Write, Description("The ExceptIfFromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.")] String ExceptIfFromScope[]; + [Write, Description("The SubjectContainsWords parameter specifies a condition for the DLP rule that looks for words or phrases in the Subject field of messages. You can specify multiple words or phrases separated by commas.")] String SubjectContainsWords[]; + [Write, Description("The SubjectMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.")] String SubjectMatchesPatterns[]; + [Write, Description("The SubjectOrBodyContainsWords parameter specifies a condition for the rule that looks for words in the Subject field or body of messages.")] String SubjectOrBodyContainsWords[]; + [Write, Description("The SubjectOrBodyMatchesPatterns parameter specifies a condition for the rule that looks for text patterns in the Subject field or body of messages.")] String SubjectOrBodyMatchesPatterns[]; + [Write, Description("The ContentCharacterSetContainsWords parameter specifies a condition for the rule that looks for character set names in messages. You can specify multiple values separated by commas.")] String ContentCharacterSetContainsWords[]; + [Write, Description("The DocumentNameMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.")] String DocumentNameMatchesPatterns[]; + [Write, Description("The DocumentNameMatchesWords parameter specifies a condition for the DLP rule that looks for words or phrases in the name of message attachments. ")] String DocumentNameMatchesWords[]; + [Write, Description("he ExceptIfAnyOfRecipientAddressContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in recipient email addresses.")] String ExceptIfAnyOfRecipientAddressContainsWords[]; + [Write, Description("The ExceptIfAnyOfRecipientAddressMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in recipient email addresses by using regular expressions.")] String ExceptIfAnyOfRecipientAddressMatchesPatterns[]; + [Write, Description("The ExceptIfContentCharacterSetContainsWords parameter specifies an exception for the rule that looks for character set names in messages.")] String ExceptIfContentCharacterSetContainsWords[]; + [Write, Description("The ExceptIfContentPropertyContainsWords parameter specifies an exception for the DLP rule that's based on a property match in content.")] String ExceptIfContentPropertyContainsWords[]; + [Write, Description("The ExceptIfDocumentNameMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.")] String ExceptIfDocumentNameMatchesPatterns[]; + [Write, Description("The ExceptIfDocumentNameMatchesWords parameter specifies an exception for the DLP rule that looks for words or phrases in the name of message attachments.")] String ExceptIfDocumentNameMatchesWords[]; + [Write, Description("The ExceptIfFromAddressContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in the sender's email address.")] String ExceptIfFromAddressContainsWords[]; + [Write, Description("The ExceptIfFromAddressMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the sender's email address by using regular expressions.")] String ExceptIfFromAddressMatchesPatterns[]; + [Write, Description("The FromAddressContainsWords parameter specifies a condition for the DLP rule that looks for words or phrases in the sender's email address.")] String FromAddressContainsWords[]; + [Write, Description("The FromAddressMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the sender's email address by using regular expressions. ")] String FromAddressMatchesPatterns[]; + [Write, Description("The ExceptIfMessageTypeMatches parameter specifies an exception for the rule that looks for messages of the specified type.")] String ExceptIfMessageTypeMatches[]; + [Write, Description("The RecipientDomainIs parameter specifies a condition for the DLP rule that looks for recipients with email addresses in the specified domains.")] String RecipientDomainIs[]; + [Write, Description("The ExceptIfRecipientDomainIs parameter specifies an exception for the DLP rule that looks for recipients with email addresses in the specified domains.")] String ExceptIfRecipientDomainIs[]; + [Write, Description("The ExceptIfSenderDomainIs parameter specifies an exception for the DLP rule that looks for messages from senders with email address in the specified domains. ")] String ExceptIfSenderDomainIs[]; + [Write, Description("The ExceptIfSenderIpRanges parameter specifies an exception for the DLP rule that looks for senders whose IP addresses matches the specified value, or fall within the specified ranges.")] String ExceptIfSenderIPRanges[]; + [Write, Description("The ExceptIfSentTo parameter specifies an exception for the DLP rule that looks for recipients in messages. You identify the recipients by email address.")] String ExceptIfSentTo[]; + [Write, Description("The ExceptIfSubjectContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in the Subject field of messages.")] String ExceptIfSubjectContainsWords[]; + [Write, Description("The ExceptIfSubjectMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.")] String ExceptIfSubjectMatchesPatterns[]; + [Write, Description("The ExceptIfSubjectOrBodyContainsWords parameter specifies an exception for the rule that looks for words in the Subject field or body of messages.")] String ExceptIfSubjectOrBodyContainsWords[]; + [Write, Description("The ExceptIfSubjectOrBodyMatchesPatterns parameter specifies an exception for the rule that looks for text patterns in the Subject field or body of messages.")] String ExceptIfSubjectOrBodyMatchesPatterns[]; + [Write, Description("The DocumentContainsWords parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.")] String DocumentContainsWords[]; + [Write, Description("The SentToMemberOf parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.")] String SentToMemberOf[]; + [Write, Description("The ContentIsNotLabeled parameter specifies if the content is labeled. A True or False condition.")] Boolean ContentIsNotLabeled; [Write, Description("The ContentExtensionMatchesWords parameter specifies a condition for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas.")] String ContentExtensionMatchesWords[]; [Write, Description("The ExceptIfContentExtensionMatchesWords parameter specifies an exception for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas.")] String ExceptIfContentExtensionMatchesWords[]; }; diff --git a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md index 2dbbf71950..aebe4746c6 100644 --- a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md +++ b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md @@ -44,7 +44,39 @@ | **ExceptIfDocumentIsPasswordProtected** | Write | Boolean | The ExceptIfDocumentIsPasswordProtected parameter specifies an exception for the DLP rule that looks for password protected files (because the contents of the file can't be inspected). Password detection only works for Office documents and .zip files. | | | **ContentExtensionMatchesWords** | Write | StringArray[] | The ContentExtensionMatchesWords parameter specifies a condition for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas. | | | **ExceptIfContentExtensionMatchesWords** | Write | StringArray[] | The ExceptIfContentExtensionMatchesWords parameter specifies an exception for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas. | | - +| **MessageTypeMatches** | Write | StringArray[] | The MessageTypeMatches parameter specifies a condition for the DLP rule that looks for types of SMIME message patterns.| | +| **FromScope** | Write | StringArray[] | The FromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.| | +| **ExceptIfFromScope** | Write | StringArray[] | The parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.| | +| **SubjectContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the Subject field of messages. You can specify multiple words or phrases separated by commas.| | +| **SubjectMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.| | +| **SubjectOrBodyContainsWords** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for words in the Subject field or body of messages.| | +| **SubjectOrBodyMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for text patterns in the Subject field or body of messages.| | +| **ContentCharacterSetContainsWords** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for character set names in messages. You can specify multiple values separated by commas.| | +| **DocumentNameMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.| | +| **DocumentNameMatchesWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the name of message attachments. | | +**ExceptIfAnyOfRecipientAddressContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in recipient email addresses.| | +| **ExceptIfAnyOfRecipientAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in recipient email addresses by using regular expressions.| | +| **ExceptIfContentCharacterSetContainsWords** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for character set names in messages.| | +| **ExceptIfContentPropertyContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that's based on a property match in content.| | +| **ExceptIfDocumentNameMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.| | +| **ExceptIfDocumentNameMatchesWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the name of message attachments.| | +| **ExceptIfFromAddressContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the sender's email address.| | +| **ExceptIfFromAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the sender's email address by using regular expressions.| | +| **FromAddressContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the sender's email address.| | +| **FromAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the sender's email address by using regular expressions. | | +| **ExceptIfMessageTypeMatches** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for messages of the specified type.| | +| **RecipientDomainIs** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for recipients with email addresses in the specified domains.| | +| **ExceptIfRecipientDomainIs** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for recipients with email addresses in the specified domains.| | +| **ExceptIfSenderDomainIs** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for messages from senders with email address in the specified domains. | | +| **ExceptIfSenderIpRanges** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for senders whose IP addresses matches the specified value, or fall within the specified ranges.| | +| **ExceptIfSentTo** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for recipients in messages. You identify the recipients by email address.| | +| **ExceptIfSubjectContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the Subject field of messages.| | +| **ExceptIfSubjectMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.| | +| **ExceptIfSubjectOrBodyContainsWords** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for words in the Subject field or body of messages.| | +| **ExceptIfSubjectOrBodyMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for text patterns in the Subject field or body of messages.| | +| **DocumentContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.| | +| **SentToMemberOf** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.| | +| **ContentIsNotLabeled** | Write | Boolean | The parameter specifies if the content is labeled. A True or False condition. | | ### MSFT_SCDLPSensitiveInformation #### Parameters From 4b25e9bb2a03008efc43cffcfa7f557594b2c035 Mon Sep 17 00:00:00 2001 From: Devin Power Date: Tue, 6 Feb 2024 09:41:04 -0500 Subject: [PATCH 079/171] Update powershell7-support.md Fixes typo under Issues loading PnP.Powershell Module section --- docs/docs/user-guide/get-started/powershell7-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/user-guide/get-started/powershell7-support.md b/docs/docs/user-guide/get-started/powershell7-support.md index b060a665e9..5b699bac5b 100644 --- a/docs/docs/user-guide/get-started/powershell7-support.md +++ b/docs/docs/user-guide/get-started/powershell7-support.md @@ -25,7 +25,7 @@ To solve this, make sure the Microsoft365DSC is properly installed under C:\Prog **Issues loading the PnP.PowerShell Module** -The PnP.PowerShell module, which is currently being used by the SharePoint Online and OndeDrive for Business workloads needs to be loaded using Windows PowerShell. In PowerShell 7+, this is done by running the **Import-Module** cmdlet using the **-UseWindowsPowerShell** switch, and requires the modules to be located under C:\Program Files\WindowsPowerShell. In order for Microsoft365DSC to work for SharePoint Online and OneDrive for Business with PowerShell 7, you need to make sure that the PnP.PowerShell module is located under C:\Program Files\WindowsPowerShell\Modules\PnP.PowerShell. This can be achieve =d by either manually moving the module to that location, or by using PowerShell 5.1 to install it using the following line: +The PnP.PowerShell module, which is currently being used by the SharePoint Online and OndeDrive for Business workloads needs to be loaded using Windows PowerShell. In PowerShell 7+, this is done by running the **Import-Module** cmdlet using the **-UseWindowsPowerShell** switch, and requires the modules to be located under C:\Program Files\WindowsPowerShell. In order for Microsoft365DSC to work for SharePoint Online and OneDrive for Business with PowerShell 7, you need to make sure that the PnP.PowerShell module is located under C:\Program Files\WindowsPowerShell\Modules\PnP.PowerShell. This can be achieved by either manually moving the module to that location, or by using PowerShell 5.1 to install it using the following line: ``` Install-Module PnP.PowerShell -Force -Scope AllUsers From ed4e62cb3ae82b8c7e8b7c8bb2eae33bab9f2cd8 Mon Sep 17 00:00:00 2001 From: Tayhall <4ndrewhall@gmail.com> Date: Tue, 6 Feb 2024 15:46:05 +0000 Subject: [PATCH 080/171] added setheader and none for blockaccessscope --- .../MSFT_SCDLPComplianceRule.psm1 | 19 ++++++++++++++++--- .../MSFT_SCDLPComplianceRule.schema.mof | 3 ++- .../SCDLPComplianceRule.md | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 index 6e2493dbc6..603ba9521a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 @@ -22,7 +22,7 @@ function Get-TargetResource $BlockAccess, [Parameter()] - [ValidateSet('All', 'PerUser')] + [ValidateSet('All', 'PerUser','None')] [System.String] $BlockAccessScope, @@ -272,6 +272,10 @@ function Get-TargetResource [System.String[]] $DocumentContainsWords, + [Parameter()] + [System.String[]] + $SetHeader, + [Parameter()] [System.Boolean] $ContentIsNotLabeled, @@ -445,6 +449,7 @@ function Get-TargetResource SentToMemberOf = $PolicyRule.FromAddressMatchesPatterns DocumentContainsWords = $PolicyRule.DocumentContainsWords ContentIsNotLabeled = $PolicyRule.ContentIsNotLabeled + SetHeader = $PolicyRule.SetHeader AnyOfRecipientAddressContainsWords = $AnyOfRecipientAddressContainsWords AnyOfRecipientAddressMatchesPatterns = $AnyOfRecipientAddressMatchesPatterns ContentExtensionMatchesWords = $ContentExtensionMatchesWords @@ -510,7 +515,7 @@ function Set-TargetResource $BlockAccess, [Parameter()] - [ValidateSet('All', 'PerUser')] + [ValidateSet('All', 'PerUser','None')] [System.String] $BlockAccessScope, @@ -760,6 +765,10 @@ function Set-TargetResource [System.String[]] $DocumentContainsWords, + [Parameter()] + [System.String[]] + $SetHeader, + [Parameter()] [System.Boolean] $ContentIsNotLabeled, @@ -955,7 +964,7 @@ function Test-TargetResource $BlockAccess, [Parameter()] - [ValidateSet('All', 'PerUser')] + [ValidateSet('All', 'PerUser','None')] [System.String] $BlockAccessScope, @@ -1205,6 +1214,10 @@ function Test-TargetResource [System.String[]] $DocumentContainsWords, + [Parameter()] + [System.String[]] + $SetHeader, + [Parameter()] [System.Boolean] $ContentIsNotLabeled, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof index af95ed23e7..b8c38f51da 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.schema.mof @@ -38,7 +38,7 @@ class MSFT_SCDLPComplianceRule : OMI_BaseResource [Required, Description("Name of the associated DLP Compliance Policy.")] String Policy; [Write, Description("The AccessScope parameter specifies a condition for the DLP rule that's based on the access scope of the content. The rule is applied to content that matches the specified access scope."), ValueMap{"InOrganization","NotInOrganization", "None"}, Values{"InOrganization","NotInOrganization", "None"}] String AccessScope; [Write, Description("The BlockAccess parameter specifies an action for the DLP rule that blocks access to the source item when the conditions of the rule are met. $true: Blocks further access to the source item that matched the rule. The owner, author, and site owner can still access the item. $false: Allows access to the source item that matched the rule. This is the default value.")] Boolean BlockAccess; - [Write, Description("The BlockAccessScope parameter specifies the scope of the block access action."), ValueMap{"All", "PerUser"}, Values{"All", "PerUser"}] String BlockAccessScope; + [Write, Description("The BlockAccessScope parameter specifies the scope of the block access action."), ValueMap{"All", "PerUser","None"}, Values{"All", "PerUser","None"}] String BlockAccessScope; [Write, Description("The Comment parameter specifies an optional comment. If you specify a value that contains spaces, enclose the value in quotation marks.")] String Comment; [Write, Description("The ContentContainsSensitiveInformation parameter specifies a condition for the rule that's based on a sensitive information type match in content. The rule is applied to content that contains the specified sensitive information type."), EmbeddedInstance("MSFT_SCDLPContainsSensitiveInformation")] String ContentContainsSensitiveInformation; [Write, Description("The ExceptIfContentContainsSensitiveInformation parameter specifies an exception for the rule that's based on a sensitive information type match in content. The rule isn't applied to content that contains the specified sensitive information type."), EmbeddedInstance("MSFT_SCDLPContainsSensitiveInformation")] String ExceptIfContentContainsSensitiveInformation; @@ -105,6 +105,7 @@ class MSFT_SCDLPComplianceRule : OMI_BaseResource [Write, Description("The DocumentContainsWords parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.")] String DocumentContainsWords[]; [Write, Description("The SentToMemberOf parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.")] String SentToMemberOf[]; [Write, Description("The ContentIsNotLabeled parameter specifies if the content is labeled. A True or False condition.")] Boolean ContentIsNotLabeled; + [Write, Description("The SetHeader The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas")] String SetHeader[]; [Write, Description("The ContentExtensionMatchesWords parameter specifies a condition for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas.")] String ContentExtensionMatchesWords[]; [Write, Description("The ExceptIfContentExtensionMatchesWords parameter specifies an exception for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas.")] String ExceptIfContentExtensionMatchesWords[]; }; diff --git a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md index aebe4746c6..f0679370ee 100644 --- a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md +++ b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md @@ -77,6 +77,7 @@ | **DocumentContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.| | | **SentToMemberOf** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.| | | **ContentIsNotLabeled** | Write | Boolean | The parameter specifies if the content is labeled. A True or False condition. | | +| **SetHeader** | Write | StringArray[] | The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas"| | ### MSFT_SCDLPSensitiveInformation #### Parameters From f82ee382ac1c99753f5c7cc1b273ae93ef9bfec3 Mon Sep 17 00:00:00 2001 From: Tayhall <4ndrewhall@gmail.com> Date: Tue, 6 Feb 2024 15:47:41 +0000 Subject: [PATCH 081/171] removed quote --- docs/docs/resources/security-compliance/SCDLPComplianceRule.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md index f0679370ee..0d09c8ef2e 100644 --- a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md +++ b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md @@ -77,7 +77,7 @@ | **DocumentContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.| | | **SentToMemberOf** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.| | | **ContentIsNotLabeled** | Write | Boolean | The parameter specifies if the content is labeled. A True or False condition. | | -| **SetHeader** | Write | StringArray[] | The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas"| | +| **SetHeader** | Write | StringArray[] | The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas| | ### MSFT_SCDLPSensitiveInformation #### Parameters From f5fa6f429fd9f028755b12e5ed7227a592d551bf Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Tue, 6 Feb 2024 20:08:20 +0100 Subject: [PATCH 082/171] Fix nested array resource comparison --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25e04b1dc7..ee57b6ed24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * M365DSCReport * Fix nested change detection for CIMInstances * Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report + FIXES [#4291](https://github.com/microsoft/Microsoft365DSC/issues/4291) # 1.24.131.2 diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index 3fabb2eff1..db573948a1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -726,10 +726,11 @@ function Compare-M365DSCConfigurations if ($null -ne $destinationResourceInstances) { - # There is a chance we found 2 instances of a CIMInstance based on its key property. + # There is a chance we found multiple instances of a CIMInstance based on its key property. # If that's the case, loop through each instance found and if at least one of them is # a perfect match, then don't consider this a drift. $foundOneMatch = $false + $foundMatchResource = $null $drift = $null foreach ($destinationResourceInstance in $destinationResourceInstances) { @@ -753,6 +754,7 @@ function Compare-M365DSCConfigurations if ($foundResourceMatch) { $foundOneMatch = $true + $foundMatchResource = $destinationResourceInstance } else { @@ -769,6 +771,7 @@ function Compare-M365DSCConfigurations { # If a match was found, clear the drift. $drift = $null + $destinationResource.$destinationPropertyName = $destinationResource.$destinationPropertyName | Where-Object { $_ -ne $foundMatchResource } } else { From 96c17f512b68448b279643ccfd272f7134fcd76f Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 6 Feb 2024 22:19:28 +0000 Subject: [PATCH 083/171] Added priority parameter --- CHANGELOG.md | 6 +++ ...neDeviceEnrollmentPlatformRestriction.psm1 | 53 ++++++++++++++++--- ...ceEnrollmentPlatformRestriction.schema.mof | 1 + 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0229cd0383..17a056725f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneDeviceEnrollmentPlatformRestriction + * Added Priority parameter + FIXES [#4081](https://github.com/microsoft/Microsoft365DSC/issues/4081) + # 1.24.131.2 * TeamsMeetingPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 index 7214303fba..f0d87f5f74 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 @@ -57,6 +57,10 @@ function Get-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [System.Int32] + $Priority, + [Parameter()] [System.String] [ValidateSet('Absent', 'Present')] @@ -107,7 +111,12 @@ function Get-TargetResource try { - $config = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $Identity -ErrorAction silentlyContinue + try { + $config = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $Identity -ErrorAction Stop + } + catch { + $config = $null + } if ($null -eq $config) { @@ -127,6 +136,7 @@ function Get-TargetResource DisplayName = $config.DisplayName Description = $config.Description DeviceEnrollmentConfigurationType = $config.DeviceEnrollmentConfigurationType.toString() + Priority = $config.Priority Ensure = 'Present' Credential = $Credential ApplicationId = $ApplicationId @@ -229,6 +239,10 @@ function Set-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [System.Int32] + $Priority, + [Parameter()] [System.String] [ValidateSet('Absent', 'Present')] @@ -258,6 +272,7 @@ function Set-TargetResource [Switch] $ManagedIdentity ) + $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters @@ -332,11 +347,20 @@ function Set-TargetResource $assignmentsHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignments Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $policy.id ` + -DeviceConfigurationPolicyId $policy.id ` -Targets $assignmentsHash ` -Repository 'deviceManagement/deviceEnrollmentConfigurations' } } + + if ($Priority) + { + $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity + $Body = @{ + priority = $Priority + } + Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body + } } elseif ($Ensure -eq 'Present' -and $currentCategory.Ensure -eq 'Present') { @@ -380,21 +404,30 @@ function Set-TargetResource #Write-Verbose ($PSBoundParameters | ConvertTo-Json -Depth 20) Update-MgBetaDeviceManagementDeviceEnrollmentConfiguration ` -BodyParameter ([hashtable]$PSBoundParameters) ` - -DeviceEnrollmentConfigurationId $Identity + -DeviceEnrollmentConfigurationId $currentCategory.Identity #Assignments from DefaultPolicy are not editable and will raise an alert - if ($Identity -notlike '*_DefaultPlatformRestrictions') + if ($currentCategory.Identity -notlike '*_DefaultPlatformRestrictions') { if ($null -ne $Assignments -and $Assignments -ne @()) { $assignmentsHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignments Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $Identity ` - -Targets $assignmentsHash ` - -Repository 'deviceManagement/deviceEnrollmentConfigurations' + -DeviceConfigurationPolicyId $currentCategory.Identity ` + -Targets $assignmentsHash ` + -Repository 'deviceManagement/deviceEnrollmentConfigurations' } } + + if ($Priority) + { + $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity + $Body = @{ + priority = $Priority + } + Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body + } } elseif ($Ensure -eq 'Absent' -and $currentCategory.Ensure -eq 'Present') { @@ -402,7 +435,7 @@ function Set-TargetResource $config = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -Filter "displayName eq '$DisplayName'" ` | Where-Object -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration' } - Remove-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $config.id + Remove-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $currentCategory.Identity } } @@ -465,6 +498,10 @@ function Test-TargetResource [Microsoft.Management.Infrastructure.CimInstance[]] $Assignments, + [Parameter()] + [System.Int32] + $Priority, + [Parameter()] [System.String] [ValidateSet('Absent', 'Present')] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.schema.mof index 673102cc1e..86c13038c2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.schema.mof @@ -36,6 +36,7 @@ class MSFT_IntuneDeviceEnrollmentPlatformRestriction : OMI_BaseResource [Write, Description("Mac restrictions based on platform, platform operating system version, and device ownership."), EmbeddedInstance("MSFT_DeviceEnrollmentPlatformRestriction")] string MacRestriction; [Write, Description("Mac OS restrictions based on platform, platform operating system version, and device ownership."), EmbeddedInstance("MSFT_DeviceEnrollmentPlatformRestriction")] string MacOSRestriction; [Write, Description("Assignments of the policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] string Assignments[]; + [Write, Description("Priority is used when a user exists in multiple groups that are assigned enrollment configuration. Users are subject only to the configuration with the lowest priority value. Inherited from deviceEnrollmentConfiguration.")] UInt32 Priority; [Write, Description("Present ensures the restriction exists, absent ensures it is removed."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] string Ensure; [Write, Description("Credentials of the Intune Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; From 89b69e5494aad03cf160b8e1c929c4671807b17a Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 6 Feb 2024 22:28:24 +0000 Subject: [PATCH 084/171] Not a problem but we can use Id of the new policy here --- .../MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 index f0d87f5f74..3807bec308 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 @@ -347,7 +347,7 @@ function Set-TargetResource $assignmentsHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignments Update-DeviceConfigurationPolicyAssignment ` - -DeviceConfigurationPolicyId $policy.id ` + -DeviceConfigurationPolicyId $policy.Id ` -Targets $assignmentsHash ` -Repository 'deviceManagement/deviceEnrollmentConfigurations' } @@ -355,7 +355,7 @@ function Set-TargetResource if ($Priority) { - $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity + $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $policy.Id $Body = @{ priority = $Priority } From ef759b1d1f602932258624afdfe0c4cd8048b8cc Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Tue, 6 Feb 2024 22:31:53 +0000 Subject: [PATCH 085/171] Policy doesn't need to be retrieved again to be removed --- .../MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 index 3807bec308..da34e7f09a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 @@ -432,8 +432,6 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentCategory.Ensure -eq 'Present') { Write-Verbose -Message "Removing Device Enrollment Platform Restriction {$DisplayName}" - $config = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -Filter "displayName eq '$DisplayName'" ` - | Where-Object -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration' } Remove-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $currentCategory.Identity } From b9cfa05dd1dd5acb9e258d678fbb5049c75a9b19 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Wed, 7 Feb 2024 09:27:49 +0000 Subject: [PATCH 086/171] Set priority only if different than current --- ...neDeviceEnrollmentPlatformRestriction.psm1 | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 index da34e7f09a..e5d66e85fe 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 @@ -291,6 +291,12 @@ function Set-TargetResource $currentCategory = Get-TargetResource @PSBoundParameters $PSBoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $PSBoundParameters.Remove('Identity') | Out-Null + $PriorityPresent = $false + if ($PSBoundParameters.Keys.Contains('Priority')) + { + $PriorityPresent = $true + $PSBoundParameters.Remove('Priority') | Out-Null + } if ($Ensure -eq 'Present' -and $currentCategory.Ensure -eq 'Absent') { @@ -351,15 +357,15 @@ function Set-TargetResource -Targets $assignmentsHash ` -Repository 'deviceManagement/deviceEnrollmentConfigurations' } - } - if ($Priority) - { - $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $policy.Id - $Body = @{ - priority = $Priority + if ($PriorityPresent -and $Priority -ne $policy.Priority) + { + $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $policy.Id + $Body = @{ + priority = $Priority + } + Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body } - Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body } } elseif ($Ensure -eq 'Present' -and $currentCategory.Ensure -eq 'Present') @@ -420,7 +426,7 @@ function Set-TargetResource } } - if ($Priority) + if ($PriorityPresent -and $Priority -ne $currentCategory.Priority) { $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity $Body = @{ From d52aa6796ae8061fee133b33b02729f77edc51e6 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Wed, 7 Feb 2024 09:37:30 +0000 Subject: [PATCH 087/171] Only set priority if not default policy --- ..._IntuneDeviceEnrollmentPlatformRestriction.psm1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 index e5d66e85fe..b6f2f20f3d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentPlatformRestriction/MSFT_IntuneDeviceEnrollmentPlatformRestriction.psm1 @@ -424,15 +424,15 @@ function Set-TargetResource -Targets $assignmentsHash ` -Repository 'deviceManagement/deviceEnrollmentConfigurations' } - } - if ($PriorityPresent -and $Priority -ne $currentCategory.Priority) - { - $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity - $Body = @{ - priority = $Priority + if ($PriorityPresent -and $Priority -ne $currentCategory.Priority) + { + $Uri = "/beta/deviceManagement/deviceEnrollmentConfigurations/{0}/setPriority" -f $currentCategory.Identity + $Body = @{ + priority = $Priority + } + Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body } - Invoke-MgGraphRequest -Method POST -Uri $Uri -Body $Body } } elseif ($Ensure -eq 'Absent' -and $currentCategory.Ensure -eq 'Present') From 82415743e742aa3e7107b0f29a089d8a5ae83e7b Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 09:32:02 -0500 Subject: [PATCH 088/171] Updates to EXO Integration Tests --- CHANGELOG.md | 2 ++ .../Dependencies/Manifest.psd1 | 2 +- ...XORecipientPermission.ps1 => 1-Create.ps1} | 5 ++-- .../EXORecipientPermission/3-Remove.ps1 | 30 +++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) rename Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/{1-EXORecipientPermission.ps1 => 1-Create.ps1} (79%) create mode 100644 Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/3-Remove.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0229cd0383..3cc23a140d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ * Fixed issue with missing ManagedIdentity parameter in Test signature. * TeamsUpdateManagementPolicy * Fixed issue with missing ManagedIdentity parameter in Set signature. +* DEPENDENCIES + * Updated MSCloudLoginAssistant to version 1.1.11 # 1.24.131.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 9cc63defeb..ce18e9c422 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -86,7 +86,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.10" + RequiredVersion = "1.1.11" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 similarity index 79% rename from Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 rename to Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 index c6d219bc54..8df472f8f0 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-EXORecipientPermission.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 @@ -15,13 +15,14 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXORecipientPermission 'AddSendAs' { - Identity = 'John' - Trustee = "admin@$OrganizationName" + Identity = 'AdeleV@$Domain' + Trustee = "admin@$Domain" AccessRights = 'SendAs' Ensure = 'Present' Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/3-Remove.ps1 new file mode 100644 index 0000000000..f263aba8e4 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/3-Remove.ps1 @@ -0,0 +1,30 @@ + +<# +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(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + $Domain = $Credscredential.Username.Split('@')[1] + node localhost + { + EXORecipientPermission 'AddSendAs' + { + + Identity = 'AdeleV@$Domain' + Trustee = "admin@$Domain" + Ensure = 'Absent' + Credential = $Credscredential + } + } +} From 736458fe86f5988f558443903860812550fc49d4 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 09:32:07 -0500 Subject: [PATCH 089/171] Update Microsoft365.psm1 --- Tests/Unit/Stubs/Microsoft365.psm1 | 968 +++++++++++++++++++++++++---- 1 file changed, 864 insertions(+), 104 deletions(-) diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index dc213dcafb..72f1b9c480 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -131,6 +131,27 @@ function Add-MailboxPermission $InheritanceType ) } +function Add-RecipientPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $AccessRights, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $Trustee + ) +} function Disable-JournalRule { [CmdletBinding()] @@ -552,8 +573,12 @@ function Get-DistributionGroup [CmdletBinding()] param( [Parameter()] - [System.String] - $SortBy, + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromDLMembersWithDisplayNames, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromWithDisplayNames, [Parameter()] [System.Management.Automation.PSCredential] @@ -579,13 +604,21 @@ function Get-DistributionGroup [System.String] $Filter, + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromSendersOrMembersWithDisplayNames, + [Parameter()] [System.Object] $ResultSize, [Parameter()] [System.String] - $Anr + $Anr, + + [Parameter()] + [System.String] + $SortBy ) } function Get-DistributionGroupMember @@ -640,6 +673,39 @@ function Get-GlobalAddressList $DefaultOnly ) } +function Get-Group +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $SortBy, + + [Parameter()] + [System.Object] + $OrganizationalUnit, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object[]] + $RecipientTypeDetails, + + [Parameter()] + [System.Object] + $ResultSize, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.String] + $Anr + ) +} function Get-HostedConnectionFilterPolicy { [CmdletBinding()] @@ -735,10 +801,6 @@ function Get-Mailbox { [CmdletBinding()] param( - [Parameter()] - [System.Management.Automation.SwitchParameter] - $ServiceSafetyConfiguration, - [Parameter()] [System.String] $SortBy, @@ -767,6 +829,18 @@ function Get-Mailbox [System.Management.Automation.SwitchParameter] $SoftDeletedMailbox, + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromSendersOrMembersWithDisplayNames, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromWithDisplayNames, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAcceptMessagesOnlyFromDLMembersWithDisplayNames, + [Parameter()] [System.Object] $ResultSize, @@ -842,17 +916,82 @@ function Get-MailboxCalendarFolder $Identity ) } -function Get-MailboxFolderStatistics +function Get-MailboxFolder { [CmdletBinding()] param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $MailFolderOnly, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $GetChildren, + [Parameter()] [System.Object] $Identity, + [Parameter()] + [System.Object] + $ResultSize, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Recurse + ) +} +function Get-MailboxFolderStatistics +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Object] + $Database, + [Parameter()] [System.String] - $FolderScope + $DiagnosticInfo, + + [Parameter()] + [System.Object] + $StoreMailboxIdentity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeOldestAndNewestItems, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UseCustomRouting, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Archive, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeSoftDeletedRecipients, + + [Parameter()] + [System.Int32] + $SkipCount, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeAnalysis, + + [Parameter()] + [System.Object] + $ResultSize, + + [Parameter()] + [System.Object] + $FolderScope, + + [Parameter()] + [System.Object] + $Identity ) } function Get-MailboxPermission @@ -1340,6 +1479,100 @@ function Get-QuarantinePolicy $QuarantinePolicyType ) } +function Get-Recipient +{ + [CmdletBinding()] + param( + [Parameter()] + [System.String] + $SortBy, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.String] + $RecipientPreviewFilter, + + [Parameter()] + [System.String] + $Anr, + + [Parameter()] + [System.String] + $BookmarkDisplayName, + + [Parameter()] + [System.Object] + $Capabilities, + + [Parameter()] + [System.Object] + $ResultSize, + + [Parameter()] + [System.Object[]] + $RecipientTypeDetails, + + [Parameter()] + [System.String[]] + $Properties, + + [Parameter()] + [System.Object] + $PropertySet, + + [Parameter()] + [System.Object] + $AuthenticationType, + + [Parameter()] + [System.String] + $Filter, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $IncludeSoftDeletedRecipients, + + [Parameter()] + [System.Object[]] + $RecipientType, + + [Parameter()] + [System.Object] + $OrganizationalUnit, + + [Parameter()] + [System.Boolean] + $IncludeBookmarkObject + ) +} +function Get-RecipientPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $ReadFromDomainController, + + [Parameter()] + [System.Object] + $AccessRights, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $ResultSize, + + [Parameter()] + [System.Object] + $Trustee + ) +} function Get-RemoteDomain { [CmdletBinding()] @@ -1368,7 +1601,11 @@ function Get-ReportSubmissionRule param( [Parameter()] [System.Object] - $Identity + $Identity, + + [Parameter()] + [System.Object] + $State ) } function Get-ResourceConfig @@ -2001,37 +2238,45 @@ function New-App [CmdletBinding()] param( [Parameter()] - [System.String] - $Etoken, + [System.Uri] + $Url, [Parameter()] - [System.IO.Stream] - $FileStream, + [System.String] + $Identity, [Parameter()] [System.Boolean] $Enabled, [Parameter()] - [System.Uri] - $Url, + [System.Object] + $AddInOverrides, [Parameter()] [System.Object] $Mailbox, + [Parameter()] + [System.IO.Stream] + $FileStream, + [Parameter()] [System.String] $MarketplaceServicesUrl, [Parameter()] - [System.Management.Automation.SwitchParameter] - $PrivateCatalog, + [System.String] + $Etoken, [Parameter()] [System.String] $MarketplaceCorrelationID, + [Parameter()] + [System.String] + $Version, + [Parameter()] [System.Object] $DefaultStateForUser, @@ -2044,6 +2289,10 @@ function New-App [System.String] $MarketplaceUserProfileType, + [Parameter()] + [System.Object] + $AllowSetting, + [Parameter()] [System.Management.Automation.SwitchParameter] $DownloadOnly, @@ -2056,10 +2305,18 @@ function New-App [System.Object] $UserList, + [Parameter()] + [System.String] + $AppState, + [Parameter()] [System.Management.Automation.SwitchParameter] $OrganizationApp, + [Parameter()] + [System.String] + $AppType, + [Parameter()] [System.String] $MarketplaceAssetID, @@ -2074,9 +2331,17 @@ function New-App [Parameter()] [System.Management.Automation.SwitchParameter] - $AllowReadWriteMailbox - ) -} + $AllowReadWriteMailbox, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $PrivateCatalog, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $UpdateAppState + ) +} function New-ApplicationAccessPolicy { [CmdletBinding()] @@ -2245,35 +2510,6 @@ function New-ClientAccessRule $Scope ) } -function New-DataClassification -{ - [CmdletBinding()] - param( - [Parameter()] - [System.String] - $Description, - - [Parameter()] - [System.String] - $Name, - - [Parameter()] - [System.Globalization.CultureInfo] - $Locale, - - [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm, - - [Parameter()] - [System.Object] - $Fingerprints, - - [Parameter()] - [System.Object] - $ClassificationRuleCollectionIdentity - ) -} function New-DataEncryptionPolicy { [CmdletBinding()] @@ -4353,7 +4589,277 @@ function New-ReportSubmissionPolicy { [CmdletBinding()] param( + [Parameter()] + [System.String] + $PostSubmitMessage, + + [Parameter()] + [System.Object] + $ReportJunkAddresses, + + [Parameter()] + [System.Boolean] + $NotificationsForPhishMalwareSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.String] + $PhishingReviewResultMessage, + + [Parameter()] + [System.String] + $PostSubmitMessageTitle, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForNotJunk, + + [Parameter()] + [System.Boolean] + $EnableCustomizedMsg, + + [Parameter()] + [System.Object] + $NotificationSenderAddress, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonTextForJunk, + + [Parameter()] + [System.Boolean] + $NotificationsForSpamSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.String] + $PostSubmitMessageForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageForPhishing, + + [Parameter()] + [System.Boolean] + $EnableThirdPartyAddress, + + [Parameter()] + [System.String] + $PreSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String] + $PreSubmitMessageForJunk, + + [Parameter()] + [System.Int32] + $UserSubmissionOptions, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonTextForPhishing, + + [Parameter()] + [System.String] + $PreSubmitMessageForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageTitleForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForNotJunk, + + [Parameter()] + [System.Boolean] + $ReportJunkToCustomizedAddress, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonLinkForPhishing, + + [Parameter()] + [System.Boolean] + $ReportNotJunkToCustomizedAddress, + + [Parameter()] + [System.String] + $PostSubmitMessageTitleForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForPhishing, + + [Parameter()] + [System.String] + $NotificationFooterMessage, + + [Parameter()] + [System.Boolean] + $EnableOrganizationBranding, + + [Parameter()] + [System.String] + $PreSubmitMessageForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForPhishing, + + [Parameter()] + [System.Boolean] + $EnableReportToMicrosoft, + + [Parameter()] + [System.String] + $PreSubmitMessageTitleForJunk, + + [Parameter()] + [System.Boolean] + $ReportChatMessageEnabled, + + [Parameter()] + [System.Object] + $ThirdPartyReportAddresses, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForJunk, + + [Parameter()] + [System.Boolean] + $NotificationsForCleanSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.String] + $PostSubmitMessageForNotJunk, + + [Parameter()] + [System.Object] + $MultiLanguageSetting, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageForJunk, + + [Parameter()] + [System.Boolean] + $DisableQuarantineReportingOption, + + [Parameter()] + [System.Object] + $ReportNotJunkAddresses, + + [Parameter()] + [System.Boolean] + $EnableUserEmailNotification, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForJunk, + + [Parameter()] + [System.String] + $PostSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageTitleForJunk, + + [Parameter()] + [System.Boolean] + $DisableUserSubmissionOptions, + + [Parameter()] + [System.Boolean] + $OnlyShowPhishingDisclaimer, + + [Parameter()] + [System.String] + $PostSubmitMessageTitleForNotJunk, + + [Parameter()] + [System.String] + $PreSubmitMessage, + + [Parameter()] + [System.String] + $PreSubmitMessageTitleForNotJunk, + + [Parameter()] + [System.String] + $JunkReviewResultMessage, + + [Parameter()] + [System.Boolean] + $EnableCustomNotificationSender, + + [Parameter()] + [System.Boolean] + $ReportChatMessageToCustomizedAddressEnabled, + + [Parameter()] + [System.Object] + $ReportPhishAddresses, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageTitleForJunk, + + [Parameter()] + [System.String] + $NotJunkReviewResultMessage, + + [Parameter()] + [System.Boolean] + $NotificationsForSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.Boolean] + $PreSubmitMessageEnabled, + + [Parameter()] + [System.Boolean] + $PostSubmitMessageEnabled, + + [Parameter()] + [System.String] + $PreSubmitMessageTitle, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForPhishing, + + [Parameter()] + [System.String] + $UserSubmissionOptionsMessage, + + [Parameter()] + [System.String] + $PostSubmitMessageForPhishing, + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonLinkForJunk, + + [Parameter()] + [System.Boolean] + $ReportPhishToCustomizedAddress ) } function New-ReportSubmissionRule @@ -4364,17 +4870,25 @@ function New-ReportSubmissionRule [System.String] $Name, + [Parameter()] + [System.Object[]] + $SentTo, + [Parameter()] [System.String] $Comments, [Parameter()] - [System.String[]] - $SentTo, + [System.Object] + $ReportSubmissionPolicy, [Parameter()] - [System.String] - $ReportSubmissionPolicy + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Boolean] + $Enabled ) } function New-RoleAssignmentPolicy @@ -5503,6 +6017,10 @@ function Remove-App [System.Object] $Identity, + [Parameter()] + [System.String] + $AppType, + [Parameter()] [System.Management.Automation.SwitchParameter] $OrganizationApp, @@ -6073,8 +6591,45 @@ function Remove-QuarantinePolicy $Identity, [Parameter()] - [System.Object] - $DomainController + [System.Object] + $DomainController + ) +} +function Remove-RecipientPermission +{ + [CmdletBinding()] + param( + [Parameter()] + [System.Management.Automation.SwitchParameter] + $SkipDomainValidationForMailContact, + + [Parameter()] + [System.Object] + $AccessRights, + + [Parameter()] + [System.Object] + $Trustee, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Deny, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $SkipDomainValidationForMailUser, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $SkipDomainValidationForSharedMailbox ) } function Remove-RemoteDomain @@ -6104,12 +6659,12 @@ function Remove-ReportSubmissionRule [CmdletBinding()] param( [Parameter()] - [System.Object] - $Identity, + [System.Management.Automation.SwitchParameter] + $Confirm, [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm + [System.Object] + $Identity ) } function Remove-RoleAssignmentPolicy @@ -9232,6 +9787,10 @@ function Set-MailContact [System.String] $CustomAttribute15, + [Parameter()] + [System.Object] + $UserSMimeCertificate, + [Parameter()] [System.Object] $ExtensionCustomAttribute1, @@ -9278,7 +9837,7 @@ function Set-MailContact [Parameter()] [System.Object] - $GrantSendOnBehalfTo, + $UserCertificate, [Parameter()] [System.Object] @@ -9296,6 +9855,10 @@ function Set-MailContact [System.Management.Automation.SwitchParameter] $ForceUpgrade, + [Parameter()] + [System.Object] + $GrantSendOnBehalfTo, + [Parameter()] [System.String] $CustomAttribute12 @@ -10042,6 +10605,10 @@ function Set-OrganizationConfig [System.Boolean] $MailTipsAllTipsEnabled, + [Parameter()] + [System.Boolean] + $PostponeRoamingSignaturesUntilLater, + [Parameter()] [System.Object] $RemotePublicFolderMailboxes, @@ -11430,107 +11997,283 @@ function Set-ReportSubmissionPolicy param( [Parameter()] [System.String] - $Identity, + $PostSubmitMessage, [Parameter()] - [System.Boolean] - $DisableQuarantineReportingOption, + [System.Object] + $ReportJunkAddresses, [Parameter()] [System.Boolean] - $EnableCustomNotificationSender, + $NotificationsForPhishMalwareSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.String] + $PhishingReviewResultMessage, + + [Parameter()] + [System.String] + $PostSubmitMessageTitle, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForNotJunk, [Parameter()] [System.Boolean] - $EnableOrganizationBranding, + $EnableCustomizedMsg, + + [Parameter()] + [System.Object] + $NotificationSenderAddress, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonTextForJunk, [Parameter()] [System.Boolean] - $EnableReportToMicrosoft, + $NotificationsForSpamSubmissionAirInvestigationsEnabled, + + [Parameter()] + [System.String] + $PostSubmitMessageForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageForPhishing, [Parameter()] [System.Boolean] $EnableThirdPartyAddress, [Parameter()] - [System.Boolean] - $EnableUserEmailNotification, + [System.String] + $PreSubmitMessageTitleForPhishing, [Parameter()] [System.String] - $JunkReviewResultMessage, + $PreSubmitMessageForJunk, + + [Parameter()] + [System.Int32] + $UserSubmissionOptions, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonTextForPhishing, [Parameter()] [System.String] - $NotJunkReviewResultMessage, + $PreSubmitMessageForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageTitleForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForNotJunk, + + [Parameter()] + [System.Boolean] + $ReportJunkToCustomizedAddress, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonLinkForPhishing, + + [Parameter()] + [System.Boolean] + $ReportNotJunkToCustomizedAddress, + + [Parameter()] + [System.String] + $PostSubmitMessageTitleForJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForPhishing, [Parameter()] [System.String] $NotificationFooterMessage, + [Parameter()] + [System.Boolean] + $EnableOrganizationBranding, + [Parameter()] [System.String] - $NotificationSenderAddress, + $PreSubmitMessageForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForNotJunk, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForPhishing, + + [Parameter()] + [System.Boolean] + $EnableReportToMicrosoft, [Parameter()] [System.String] - $PhishingReviewResultMessage, + $PreSubmitMessageTitleForJunk, + + [Parameter()] + [System.Boolean] + $ReportChatMessageEnabled, + + [Parameter()] + [System.Object] + $ThirdPartyReportAddresses, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageButtonLinkForJunk, + + [Parameter()] + [System.Boolean] + $NotificationsForCleanSubmissionAirInvestigationsEnabled, [Parameter()] [System.String] - $PostSubmitMessage, + $PostSubmitMessageForNotJunk, + + [Parameter()] + [System.Object] + $MultiLanguageSetting, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageForJunk, [Parameter()] [System.Boolean] - $PostSubmitMessageEnabled, + $DisableQuarantineReportingOption, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm, + + [Parameter()] + [System.Object] + $ReportNotJunkAddresses, + + [Parameter()] + [System.Boolean] + $EnableUserEmailNotification, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageForJunk, [Parameter()] [System.String] - $PostSubmitMessageTitle, + $PostSubmitMessageTitleForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePreSubmitMessageTitleForJunk, + + [Parameter()] + [System.Boolean] + $DisableUserSubmissionOptions, + + [Parameter()] + [System.Boolean] + $OnlyShowPhishingDisclaimer, + + [Parameter()] + [System.String] + $PostSubmitMessageTitleForNotJunk, [Parameter()] [System.String] $PreSubmitMessage, [Parameter()] - [System.Boolean] - $PreSubmitMessageEnabled, + [System.String] + $PreSubmitMessageTitleForNotJunk, [Parameter()] [System.String] - $PreSubmitMessageTitle, + $JunkReviewResultMessage, [Parameter()] - [System.String[]] - $ReportJunkAddresses = @(), + [System.Boolean] + $EnableCustomNotificationSender, [Parameter()] [System.Boolean] - $ReportJunkToCustomizedAddress, + $ReportChatMessageToCustomizedAddressEnabled, + + [Parameter()] + [System.Object] + $ReportPhishAddresses, [Parameter()] [System.String[]] - $ReportNotJunkAddresses = @(), + $MultiLanguagePostSubmitMessageTitleForJunk, + + [Parameter()] + [System.String] + $NotJunkReviewResultMessage, [Parameter()] [System.Boolean] - $ReportNotJunkToCustomizedAddress, + $NotificationsForSubmissionAirInvestigationsEnabled, [Parameter()] - [System.String[]] - $ReportPhishAddresses = @(), + [System.Boolean] + $PreSubmitMessageEnabled, [Parameter()] [System.Boolean] - $ReportPhishToCustomizedAddress, + $PostSubmitMessageEnabled, + + [Parameter()] + [System.String] + $PreSubmitMessageTitle, [Parameter()] [System.String[]] - $ThirdPartyReportAddresses = @(), + $MultiLanguagePreSubmitMessageTitleForPhishing, [Parameter()] - [System.Management.Automation.SwitchParameter] - $Confirm + [System.String[]] + $MultiLanguagePreSubmitMessageButtonTextForPhishing, + + [Parameter()] + [System.String] + $UserSubmissionOptionsMessage, + + [Parameter()] + [System.String] + $PostSubmitMessageForPhishing, + + [Parameter()] + [System.String[]] + $MultiLanguagePostSubmitMessageButtonLinkForJunk, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.Boolean] + $ReportPhishToCustomizedAddress ) } function Set-ReportSubmissionRule @@ -11539,15 +12282,23 @@ function Set-ReportSubmissionRule param( [Parameter()] [System.String] - $Identity, + $Name, + + [Parameter()] + [System.Object[]] + $SentTo, [Parameter()] [System.String] $Comments, [Parameter()] - [System.String[]] - $SentTo, + [System.Object] + $Identity, + + [Parameter()] + [System.Object] + $ReportSubmissionPolicy, [Parameter()] [System.Management.Automation.SwitchParameter] @@ -12927,7 +13678,11 @@ function Set-User param( [Parameter()] [System.String] - $Company, + $MailboxRegion, + + [Parameter()] + [System.Boolean] + $IsShadowMailbox, [Parameter()] [System.String] @@ -12982,8 +13737,8 @@ function Set-User $Force, [Parameter()] - [System.String] - $LastName, + [System.Object] + $ManagedOnboardingType, [Parameter()] [System.Management.Automation.SwitchParameter] @@ -13022,8 +13777,8 @@ function Set-User $AssistantName, [Parameter()] - [System.Object] - $OtherHomePhone, + [System.String] + $Company, [Parameter()] [System.String] @@ -13046,12 +13801,12 @@ function Set-User $Notes, [Parameter()] - [System.Management.Automation.SwitchParameter] - $PermanentlyClearPreviousMailboxInfo, + [System.String] + $LastName, [Parameter()] - [System.String] - $MailboxRegion, + [System.Management.Automation.SwitchParameter] + $PermanentlyClearPreviousMailboxInfo, [Parameter()] [System.Object] @@ -13097,6 +13852,10 @@ function Set-User [System.Object] $WindowsEmailAddress, + [Parameter()] + [System.String] + $StreetAddress, + [Parameter()] [System.Boolean] $RemotePowerShellEnabled, @@ -13110,8 +13869,8 @@ function Set-User $GeoCoordinates, [Parameter()] - [System.String] - $StreetAddress, + [System.Object] + $OtherHomePhone, [Parameter()] [System.Object] @@ -13144,6 +13903,7 @@ function Update-RoleGroupMember ) } #endregion + #region Microsoft.Graph.Applications function Get-MgApplication { From 1b3201205ac1c1d3a7fbb546a54ed18cfaab5213 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 09:35:54 -0500 Subject: [PATCH 090/171] Updated * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180 --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cc23a140d..5369cd8e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * TeamsUpdateManagementPolicy * Fixed issue with missing ManagedIdentity parameter in Set signature. * DEPENDENCIES + * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. * Updated MSCloudLoginAssistant to version 1.1.11 # 1.24.131.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index ce18e9c422..db8d949b4a 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -78,7 +78,7 @@ }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' - RequiredVersion = '2.0.178' + RequiredVersion = '2.0.180' }, @{ ModuleName = 'MicrosoftTeams' From c9f71d6123502bd08000231bb7657a27e7bae1e9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 10:05:46 -0500 Subject: [PATCH 091/171] Updated ReverseDSC --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5369cd8e5e..a8ef3cb3e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * DEPENDENCIES * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. * Updated MSCloudLoginAssistant to version 1.1.11 + * Updated ReverseDSC to version 2.0.0.19 # 1.24.131.1 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index db8d949b4a..6c1877c352 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -94,7 +94,7 @@ }, @{ ModuleName = 'ReverseDSC' - RequiredVersion = '2.0.0.18' + RequiredVersion = '2.0.0.19' } ) } From 20221fc88d4724b893455ee13edfc5a4ed74d89c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 10:22:16 -0500 Subject: [PATCH 092/171] Fixes Unit Tests --- CHANGELOG.md | 11 +++++++---- .../Microsoft365DSC.EXODataClassification.Tests.ps1 | 7 ------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8ef3cb3e2..7bbf82467b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,18 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* DEPENDENCIES + * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. + * Updated MSCloudLoginAssistant to version 1.1.11 + * Updated ReverseDSC to version 2.0.0.19 + # 1.24.131.2 * TeamsMeetingPolicy * Fixed issue with missing ManagedIdentity parameter in Test signature. * TeamsUpdateManagementPolicy * Fixed issue with missing ManagedIdentity parameter in Set signature. -* DEPENDENCIES - * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. - * Updated MSCloudLoginAssistant to version 1.1.11 - * Updated ReverseDSC to version 2.0.0.19 # 1.24.131.1 diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 index e2c9b7fe7d..061e44f6e2 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 @@ -31,9 +31,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { return 'Credentials' } - Mock -CommandName New-DataClassification -MockWith { - } - Mock -CommandName Set-DataClassification -MockWith { } @@ -58,10 +55,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-DataClassification -MockWith { return $null } - - Mock -CommandName New-DataClassification -MockWith { - - } } It 'Should return False from the Get method' { From e5b1b37ba0ba7719d937f07b6b125115140b95dc Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 11:02:10 -0500 Subject: [PATCH 093/171] TeamsMeetingPolicy --- CHANGELOG.md | 3 +++ .../MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bbf82467b..7e8641e984 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # UNRELEASED +* TeamsMeetingPolicy + * Ignore the AllowUserToJoinExternalMeeting parameterfor drift evaluation + since it doesn't do anything based on official documentation. * DEPENDENCIES * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. * Updated MSCloudLoginAssistant to version 1.1.11 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 index 494656a498..a3cf1bedbb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_TeamsMeetingPolicy/MSFT_TeamsMeetingPolicy.psm1 @@ -1118,6 +1118,9 @@ function Test-TargetResource # The AllowIPVideo is temporarly not working, therefore we won't check the value. $ValuesToCheck.Remove('AllowIPVideo') | Out-Null + # The AllowUserToJoinExternalMeeting doesn't do anything based on official documentation + $ValuesToCheck.Remove('AllowUserToJoinExternalMeeting') | Out-Null + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` -DesiredValues $PSBoundParameters ` From acee04fdc1790ae01a98774b2a5bc29234f91b5d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 13:04:34 -0500 Subject: [PATCH 094/171] SCDLPCOmplianceRule Fancy Quotes Handling --- CHANGELOG.md | 2 ++ .../MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e5bdb9bc..86234791ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* SCDLPComplianceRule + * Properly escapes fancy quotes in the Get method. * TeamsMeetingPolicy * Ignore the AllowUserToJoinExternalMeeting parameterfor drift evaluation since it doesn't do anything based on official documentation. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 index 981dd8ac89..452eeb1575 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 @@ -246,6 +246,7 @@ function Get-TargetResource $ExceptIfContentExtensionMatchesWords = $PolicyRule.ExceptIfContentExtensionMatchesWords.Replace(' ', '').Split(',') } + $fancyDoubleQuotes = "[\u201C\u201D]" $result = @{ Ensure = 'Present' Name = $PolicyRule.Name @@ -262,8 +263,8 @@ function Get-TargetResource GenerateIncidentReport = $PolicyRule.GenerateIncidentReport IncidentReportContent = $ArrayIncidentReportContent NotifyAllowOverride = $NotifyAllowOverrideValue - NotifyEmailCustomText = $PolicyRule.NotifyEmailCustomText - NotifyPolicyTipCustomText = $PolicyRule.NotifyPolicyTipCustomText + NotifyEmailCustomText = [regex]::Replace($PolicyRule.NotifyEmailCustomText, $fancyDoubleQuotes, '"') + NotifyPolicyTipCustomText = [regex]::Replace($PolicyRule.NotifyPolicyTipCustomText, $fancyDoubleQuotes, '"') NotifyUser = $PolicyRule.NotifyUser ReportSeverityLevel = $PolicyRule.ReportSeverityLevel RuleErrorAction = $PolicyRule.RuleErrorAction From 51557ddfc67443c258b70e172fa6057114fc0074 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 7 Feb 2024 14:11:00 -0500 Subject: [PATCH 095/171] Release 1.24.207.1 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 44 ++++++-------------- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4567ef857a..65b0f8be87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction * Added Priority parameter diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index bd1c11a715..45bb8020db 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-02 +# Generated on: 2024-02-07 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.131.2' + ModuleVersion = '1.24.207.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -140,38 +140,18 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* EXOAvailabilityAddressSpace - * Added support for the TargetServiceEpr and TargetTenantId parameters. - * Fixed the logic to retrieve existing instance by Forest Name. - * EXODistributionGroup - * The Get function now retrieves the ModeratedBy and ManagedBy properties - by the users UPN instead of their GUID. - * EXOHostedContentFilterRule - * Changed logic to retrieve the Rules by name. Using the Policys name instead. - * EXOIntraOrganizationConnector - * Fixes the DiscoveryEndpoint value from the Get method to include trailing - forward slash. - * EXOMalwareFilterRule - * Fixed an issue retrieving the right value for the Enabled property - * EXOOMEConfiguration - * Fixes an error in the Get method where the ExternalMailExpiryInDays property - wasnt properly returned. - * EXOSafeLinksPolicy - * Deprecated the UseTranslatedNotificationText property - * TeamsEmergencyCallRoutingPolicy - * Fix deletion of resource - FIXES [#4261](https://github.com/microsoft/Microsoft365DSC/issues/4261) + ReleaseNotes = '* IntuneDeviceEnrollmentPlatformRestriction + * Added Priority parameter + FIXES [#4081](https://github.com/microsoft/Microsoft365DSC/issues/4081) + * SCDLPComplianceRule + * Properly escapes fancy quotes in the Get method. * TeamsMeetingPolicy - * Fixed issue with missing ManagedIdentity parameter in Test signature. - * TeamsUpdateManagementPolicy - * Fixed issue with missing ManagedIdentity parameter in Set signature. - * TEAMS - * Added support for ManagedIdentity Authentication across Teams resources. + * Ignore the AllowUserToJoinExternalMeeting parameterfor drift evaluation + since it doesnt do anything based on official documentation. * DEPENDENCIES - * Updated MSCloudLoginAssistant dependencies to version 1.1.10. - * MISC - * Change the way to Export encoding is done so that it no longer relies - on the Get-DSCResource function.' + * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. + * Updated MSCloudLoginAssistant to version 1.1.11 + * Updated ReverseDSC to version 2.0.0.19' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 20f23407cc596a2811f0eb44cd0ed70463946c90 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Wed, 7 Feb 2024 22:42:52 +0000 Subject: [PATCH 096/171] Fix remaining issues of resource --- CHANGELOG.md | 9 ++++++ ...SettingCatalogASRRulesPolicyWindows10.psm1 | 30 +++++++++---------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..c1440eeedd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneSettingCatalogASRRulesPolicyWindows10 + * Fix removal of resource if Identity comes from another tenant or is not + present in blueprint + * Fix Test-TargetResource by not comparing Identity since it might be from + another tenant or not present in blueprint + FIXES [#4302](https://github.com/microsoft/Microsoft365DSC/issues/4302) + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 index 4be3e15f1b..062a372eaf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10/MSFT_IntuneSettingCatalogASRRulesPolicyWindows10.psm1 @@ -183,7 +183,14 @@ function Get-TargetResource try { #Retrieve policy general settings - $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ErrorAction silentlyContinue + try + { + $policy = Get-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity -ErrorAction Stop + } + catch + { + $policy = $null + } if ($null -eq $policy) { @@ -453,13 +460,7 @@ function Set-TargetResource #endregion $currentPolicy = Get-TargetResource @PSBoundParameters - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null + $PSBoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters $templateReferenceId = 'e8c053d6-9f95-42b1-a7f1-ebfd71c67a4b_1' @@ -533,7 +534,7 @@ function Set-TargetResource elseif ($Ensure -eq 'Absent' -and $currentPolicy.Ensure -eq 'Present') { Write-Verbose -Message "Removing Endpoint Protection Attack Surface Protection rules Policy {$DisplayName}" - Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $Identity + Remove-MgBetaDeviceManagementConfigurationPolicy -DeviceManagementConfigurationPolicyId $currentPolicy.Identity } } @@ -709,15 +710,12 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of Endpoint Protection Attack Surface Protection rules Policy {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Identity') | Out-Null Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - - $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { From 7df5c81be471e0536af7e470498fedbeb51fbc62 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 11:37:26 +0000 Subject: [PATCH 097/171] Fixed tests so that resource reports its correct state --- CHANGELOG.md | 9 + .../MSFT_IntuneAppConfigurationPolicy.psm1 | 227 ++++++++---------- ...FT_IntuneAppConfigurationPolicy.schema.mof | 1 + 3 files changed, 110 insertions(+), 127 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..b673e59f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneAppConfigurationPolicy + * Added parameter Id to avoid having to retrieve the same policy multiple + times + * Fixed tests in Test-TargetResource to ensure the resource reports its + correct state + FIXES [#3542](https://github.com/microsoft/Microsoft365DSC/issues/3542) + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 index 2352b5643f..d8575c1170 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 @@ -4,6 +4,10 @@ function Get-TargetResource [OutputType([System.Collections.Hashtable])] param ( + [Parameter()] + [System.String] + $Id, + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -50,7 +54,7 @@ function Get-TargetResource $ManagedIdentity ) - Write-Verbose -Message "Getting configuration of Intune App Configuration Policy {$DisplayName}" + Write-Verbose -Message "Getting configuration of Intune App Configuration Policy with Id {$Id}" $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters @@ -72,17 +76,39 @@ function Get-TargetResource $nullResult.Ensure = 'Absent' try { - $configPolicy = Get-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -Filter "displayName eq '$DisplayName'" ` - -ErrorAction Stop + + try { + $configPolicy = Get-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -TargetedManagedAppConfigurationId $Id ` + -ErrorAction Stop + } + catch { + $configPolicy = $null + } if ($null -eq $configPolicy) { - Write-Verbose -Message "No App Configuration Policy with displayName {$DisplayName} was found" - return $nullResult + Write-Verbose -Message "Could not find an Intune App Configuration Policy with Id {$Id}, searching by DisplayName {$DisplayName}" + + try + { + $configPolicy = Get-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -Filter "displayName eq '$DisplayName'" ` + -ErrorAction Stop + } + catch + { + $configPolicy = $null + } + + if ($null -eq $configPolicy) + { + Write-Verbose -Message "No App Configuration Policy with DisplayName {$DisplayName} was found" + return $nullResult + } } - Write-Verbose -Message "Found App Configuration Policy with displayName {$DisplayName}" + Write-Verbose -Message "Found App Configuration Policy with Id {$($configPolicy.Id)} and DisplayName {$($configPolicy.DisplayName)}" $returnHashtable = @{ + Id = $configPolicy.Id DisplayName = $configPolicy.DisplayName Description = $configPolicy.Description CustomSettings = $configPolicy.customSettings @@ -129,6 +155,10 @@ function Set-TargetResource [CmdletBinding()] param ( + [Parameter()] + [System.String] + $Id, + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -217,7 +247,7 @@ function Set-TargetResource if ($policy.id) { - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $policy.id ` -Targets $assignmentsHash ` -Repository 'deviceAppManagement/targetedManagedAppConfigurations' } @@ -226,10 +256,9 @@ function Set-TargetResource elseif ($Ensure -eq 'Present' -and $currentconfigPolicy.Ensure -eq 'Present') { Write-Verbose -Message "Updating Intune App Configuration Policy {$DisplayName}" - $configPolicy = Get-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -Filter "displayName eq '$DisplayName'" $updateParams = @{ - targetedManagedAppConfigurationId = $configPolicy.Id + targetedManagedAppConfigurationId = $currentconfigPolicy.Id displayName = $DisplayName description = $Description } @@ -245,15 +274,14 @@ function Set-TargetResource { $assignmentsHash += Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $Assignment } - Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $configPolicy.id ` + Update-DeviceConfigurationPolicyAssignment -DeviceConfigurationPolicyId $currentconfigPolicy.Id ` -Targets $assignmentsHash ` -Repository 'deviceAppManagement/targetedManagedAppConfigurations' } elseif ($Ensure -eq 'Absent' -and $currentconfigPolicy.Ensure -eq 'Present') { Write-Verbose -Message "Removing Intune App Configuration Policy {$DisplayName}" - $configPolicy = Get-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -Filter "displayName eq '$DisplayName'" - Remove-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -TargetedManagedAppConfigurationId $configPolicy.id + Remove-MgBetaDeviceAppManagementTargetedManagedAppConfiguration -TargetedManagedAppConfigurationId $currentconfigPolicy.Id } } @@ -263,6 +291,10 @@ function Test-TargetResource [OutputType([System.Boolean])] param ( + [Parameter()] + [System.String] + $Id, + [Parameter(Mandatory = $true)] [System.String] $DisplayName, @@ -308,6 +340,7 @@ function Test-TargetResource [Switch] $ManagedIdentity ) + #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -322,99 +355,78 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of Intune App Configuration Policy {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Id') | Out-Null - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - - if ($null -ne $CurrentValues.CustomSettings -and $CurrentValues.CustomSettings.Length -gt 0 -and $null -ne $CustomSettings) + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { - $value = Test-M365DSCAppConfigurationPolicyCustomSetting -Current $CurrentValues.CustomSettings -Desired $CustomSettings - if ($value -eq $false) - { - return $false - } + Write-Verbose -Message "Test-TargetResource returned $false" + return $false } - else + if ($CurrentValues.Ensure -eq 'Absent' -and $PSBoundParameters.Ensure -eq 'Absent') { - if (($null -eq $CurrentValues.CustomSettings -and $null -ne $CustomSettings) -or - ($null -ne $CurrentValues.CustomSettings -and $null -eq $CustomSettings)) - { - return $false - } + Write-Verbose -Message "Test-TargetResource returned $true" + return $true } - - $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null - $ValuesToCheck.Remove('CustomSettings') | Out-Null - - #region Assignments $testResult = $true - if ((-not $CurrentValues.Assignments) -xor (-not $ValuesToCheck.Assignments)) - { - Write-Verbose -Message 'Configuration drift: one the assignment is null' - return $false - } - - if ($CurrentValues.Assignments) + #Compare Cim instances + foreach ($key in $PSBoundParameters.Keys) { - if ($CurrentValues.Assignments.count -ne $ValuesToCheck.Assignments.count) + $source = $PSBoundParameters.$key + $target = $CurrentValues.$key + if ($source.getType().Name -like '*CimInstance*') { - Write-Verbose -Message "Configuration drift: Number of assignment has changed - current {$($CurrentValues.Assignments.count)} target {$($ValuesToCheck.Assignments.count)}" - return $false - } - foreach ($assignment in $CurrentValues.Assignments) - { - #GroupId Assignment - if (-not [String]::IsNullOrEmpty($assignment.groupId)) - { - $source = [Array]$ValuesToCheck.Assignments | Where-Object -FilterScript { $_.groupId -eq $assignment.groupId } - if (-not $source) - { - Write-Verbose -Message "Configuration drift: groupId {$($assignment.groupId)} not found" - $testResult = $false - break - } - $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment - } - #AllDevices/AllUsers assignment - else + $source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source + + $testResult = Compare-M365DSCComplexObject ` + -Source ($source) ` + -Target ($target) + + if ($key -eq "Assignments") { - $source = [Array]$ValuesToCheck.Assignments | Where-Object -FilterScript { $_.dataType -eq $assignment.dataType } - if (-not $source) + $testResult = $source.count -eq $target.count + if (-Not $testResult) { break } + foreach ($assignment in $source) { - Write-Verbose -Message "Configuration drift: {$($assignment.dataType)} not found" - $testResult = $false - break + if ($assignment.dataType -like '*GroupAssignmentTarget') + { + $testResult = $null -ne ($target | Where-Object {$_.dataType -eq $assignment.DataType -and $_.groupId -eq $assignment.groupId}) + #Using assignment groupDisplayName only if the groupId is not found in the directory otherwise groupId should be the key + if (-not $testResult) + { + $groupNotFound = $null -eq (Get-MgGroup -GroupId ($assignment.groupId) -ErrorAction SilentlyContinue) + } + if (-not $testResult -and $groupNotFound) + { + $testResult = $null -ne ($target | Where-Object {$_.dataType -eq $assignment.DataType -and $_.groupDisplayName -eq $assignment.groupDisplayName}) + } + } + else + { + $testResult = $null -ne ($target | Where-Object {$_.dataType -eq $assignment.DataType}) + } + if (-Not $testResult) { break } } - $sourceHash = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $source - $testResult = Compare-M365DSCComplexObject -Source $sourceHash -Target $assignment - } - - if (-not $testResult) - { - $testResult = $false - break + if (-Not $testResult) { break } } + if (-Not $testResult) { break } + $ValuesToCheck.Remove($key) | Out-Null } } - if (-not $testResult) - { - return $false - } - $ValuesToCheck.Remove('Assignments') | Out-Null - #endregion + 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 + if ($TestResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $TestResult" @@ -487,6 +499,7 @@ function Export-TargetResource { Write-Host " |---[$i/$($configPolicies.Count)] $($configPolicy.displayName)" -NoNewline $params = @{ + Id = $configPolicy.Id DisplayName = $configPolicy.displayName Ensure = 'Present' Credential = $Credential @@ -568,46 +581,6 @@ function Export-TargetResource } } -function Test-M365DSCAppConfigurationPolicyCustomSetting -{ - [CmdletBinding()] - [OutputType([System.Boolean])] - param( - [parameter(Mandatory = $true)] - [System.Object[]] - $Current, - - [parameter(Mandatory = $true)] - [System.Object[]] - $Desired - ) - if ($Current.Length -ne $Desired.Length) - { - return $false - } - - foreach ($desiredSetting in $Desired) - { - $found = $false - foreach ($currentSetting in $Current) - { - if ($currentSetting.Name -eq $desiredSetting.Name) - { - if ($currentSetting.Value -ne $desiredSetting.Value) - { - return $false - } - $found = $true - } - } - if (-not $found) - { - return $false - } - } - return $true -} - function Get-M365DSCIntuneAppConfigurationPolicyCustomSettingsAsString { [CmdletBinding()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.schema.mof index 6f6d637942..afa2e1ce50 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.schema.mof @@ -19,6 +19,7 @@ class MSFT_IntuneAppConfigurationPolicyCustomSetting [ClassVersion("1.0.0.0"), FriendlyName("IntuneAppConfigurationPolicy")] class MSFT_IntuneAppConfigurationPolicy : OMI_BaseResource { + [Write, Description("Key of the entity. Read-Only.")] String Id; [Key, Description("Display name of the app configuration policy.")] String DisplayName; [Write, Description("Description of the app configuration policy.")] String Description; [Write, Description("Assignments of the Intune Policy."), EmbeddedInstance("MSFT_DeviceManagementConfigurationPolicyAssignments")] String Assignments[]; From 0b62229b3f618039dbdbc8f3fdedf755da6601b4 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 12:00:48 +0000 Subject: [PATCH 098/171] Fix Test-TargetResource to ensure that resource reports its correct state --- CHANGELOG.md | 6 ++++ ...eviceAndAppManagementAssignmentFilter.psm1 | 35 ++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..bdbf8da965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneDeviceAndAppManagementAssignmentFilter + * Fixed Test-TargetResource to ensure that resource reports its correct state + FIXES [#3959](https://github.com/microsoft/Microsoft365DSC/issues/3959) + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceAndAppManagementAssignmentFilter/MSFT_IntuneDeviceAndAppManagementAssignmentFilter.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceAndAppManagementAssignmentFilter/MSFT_IntuneDeviceAndAppManagementAssignmentFilter.psm1 index fe0f04941d..1c043b3278 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceAndAppManagementAssignmentFilter/MSFT_IntuneDeviceAndAppManagementAssignmentFilter.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceAndAppManagementAssignmentFilter/MSFT_IntuneDeviceAndAppManagementAssignmentFilter.psm1 @@ -310,21 +310,32 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of assignment filter {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Identity') | Out-Null - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) + { + Write-Verbose -Message "Test-TargetResource returned $false" + return $false + } + if ($CurrentValues.Ensure -eq 'Absent' -and $PSBoundParameters.Ensure -eq 'Absent') + { + Write-Verbose -Message "Test-TargetResource returned $true" + return $true + } + $testResult = $true - $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null - $ValuesToCheck.Remove('Identity') | 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 + if ($TestResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $TestResult" From 0996819b19eb84a08ebefcba4b38ad4060ff4ed7 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 12:46:10 +0000 Subject: [PATCH 099/171] Use correct filter --- ...IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 index abd502c21c..71f0596ec9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 @@ -93,7 +93,7 @@ function Get-TargetResource $getValue = Get-MgBetaDeviceManagementDeviceConfiguration ` -Filter "DisplayName eq '$DisplayName'" ` -ErrorAction SilentlyContinue | Where-Object -FilterScript { ` - $_.AdditionalProperties -eq '#microsoft.graph.windows10NetworkBoundaryConfiguration' ` + $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10NetworkBoundaryConfiguration' } } } From c60ced498a01bce5fea2c5767dfafef0634591b8 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 14:20:30 +0000 Subject: [PATCH 100/171] Remove Id from being tested and auth methods --- ...igurationNetworkBoundaryPolicyWindows10.psm1 | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 index 71f0596ec9..03cb95351f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 @@ -269,15 +269,7 @@ function Set-TargetResource #endregion $currentInstance = Get-TargetResource @PSBoundParameters - - $PSBoundParameters.Remove('Ensure') | Out-Null - $PSBoundParameters.Remove('Credential') | Out-Null - $PSBoundParameters.Remove('ApplicationId') | Out-Null - $PSBoundParameters.Remove('ApplicationSecret') | Out-Null - $PSBoundParameters.Remove('TenantId') | Out-Null - $PSBoundParameters.Remove('CertificateThumbprint') | Out-Null - $PSBoundParameters.Remove('ManagedIdentity') | Out-Null - $PSBoundParameters.Remove('Verbose') | Out-Null + $PSBoundParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters if ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Absent') { @@ -434,6 +426,8 @@ function Test-TargetResource $CurrentValues = Get-TargetResource @PSBoundParameters $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck + $ValuesToCheck.Remove('Id') | Out-Null if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { @@ -465,11 +459,6 @@ function Test-TargetResource } } - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" From c33229e5eb83213d618e39343272fd0215fb4b37 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 14:23:33 +0000 Subject: [PATCH 101/171] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..e742860a82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10 + * Fixed Test-TargetResource by removing Id from begin tested and also used + correct filter while retrieving the policy otherwise it could not be found + FIXES [#3964](https://github.com/microsoft/Microsoft365DSC/issues/3964) + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction From 7f22867f69b16b74b77f354fd81c100337f1dd5e Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 14:26:26 +0000 Subject: [PATCH 102/171] Fix typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e742860a82..05dc2588b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ # UNRELEASED * IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10 - * Fixed Test-TargetResource by removing Id from begin tested and also used + * Fixed Test-TargetResource by removing Id from being tested and also used correct filter while retrieving the policy otherwise it could not be found FIXES [#3964](https://github.com/microsoft/Microsoft365DSC/issues/3964) From 9de19f1682a575c964a44093860cc2a197f10089 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 14:30:09 +0000 Subject: [PATCH 103/171] Backticks not required here --- ...neDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 index 03cb95351f..63532eaf41 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10/MSFT_IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10.psm1 @@ -92,7 +92,7 @@ function Get-TargetResource { $getValue = Get-MgBetaDeviceManagementDeviceConfiguration ` -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue | Where-Object -FilterScript { ` + -ErrorAction SilentlyContinue | Where-Object -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10NetworkBoundaryConfiguration' } } @@ -527,8 +527,8 @@ function Export-TargetResource [array]$getValue = Get-MgBetaDeviceManagementDeviceConfiguration ` -All ` -ErrorAction Stop | Where-Object ` - -FilterScript { ` - $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10NetworkBoundaryConfiguration' ` + -FilterScript { + $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10NetworkBoundaryConfiguration' } #endregion From 47e6bb376c5258b0529ee7a207589cd07310bda4 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 15:05:57 +0000 Subject: [PATCH 104/171] Remove auth methods from testing --- ...ConfigurationPolicyAndroidWorkProfile.psm1 | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 index 7a3020057a..449a699bbf 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 @@ -644,8 +644,8 @@ function Set-TargetResource { Write-Verbose -Message "Updating existing Device Configuration Policy {$DisplayName}" $configDevicePolicy = Get-MgBetaDeviceManagementDeviceConfiguration -Filter "DisplayName eq '$Displayname'" -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { ` - $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.androidWorkProfileGeneralDeviceConfiguration' ` + -FilterScript { + $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.androidWorkProfileGeneralDeviceConfiguration' } $PSBoundParameters.Remove('DisplayName') | Out-Null @@ -673,7 +673,7 @@ function Set-TargetResource { Write-Verbose -Message "Removing Device Configuration Policy {$DisplayName}" $configDevicePolicy = Get-MgBetaDeviceManagementDeviceConfiguration -Filter "DisplayName eq '$Displayname'" -ErrorAction SilentlyContinue | Where-Object ` - -FilterScript { ` + -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.androidWorkProfileGeneralDeviceConfiguration' ` } @@ -929,24 +929,17 @@ function Test-TargetResource Write-Verbose -Message "Testing configuration of Device Configuration Policy {$DisplayName}" $CurrentValues = Get-TargetResource @PSBoundParameters - - Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" - Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" - - $ValuesToCheck = $PSBoundParameters - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null + $ValuesToCheck = ([Hashtable]$PSBoundParameters).clone() + $ValuesToCheck = Remove-M365DSCAuthenticationParameter -BoundParameters $ValuesToCheck if ($CurrentValues.Ensure -ne $PSBoundParameters.Ensure) { Write-Verbose -Message "Test-TargetResource returned $false" return $false } - #region Assignments $testResult = $true + #region Assignments if ((-not $CurrentValues.Assignments) -xor (-not $ValuesToCheck.Assignments)) { Write-Verbose -Message 'Configuration drift: one the assignment is null' @@ -1004,10 +997,16 @@ function Test-TargetResource $ValuesToCheck.Remove('Assignments') | Out-Null #endregion - $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` - -Source $($MyInvocation.MyCommand.Source) ` - -DesiredValues $PSBoundParameters ` - -ValuesToCheck $ValuesToCheck.Keys + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + if ($TestResult) + { + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + } Write-Verbose -Message "Test-TargetResource returned $TestResult" From 050f282d7d12ebf670cca99fff993ee8d06045f4 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 15:06:36 +0000 Subject: [PATCH 105/171] Export, and test, correct variable --- .../MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 index 449a699bbf..66ee61a4f1 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile/MSFT_IntuneDeviceConfigurationPolicyAndroidWorkProfile.psm1 @@ -285,7 +285,7 @@ function Get-TargetResource RequiredPasswordComplexity = $policy.AdditionalProperties.requiredPasswordComplexity WorkProfileAllowAppInstallsFromUnknownSources = $policy.AdditionalProperties.workProfileAllowAppInstallsFromUnknownSources WorkProfileDataSharingType = $policy.AdditionalProperties.workProfileDataSharingType - WorkProfileBlockNotificationsWhileDeviceLocked = $policy.AdditionalProperties.WorkProfileBlockNotificationsWhileDeviceLocked + WorkProfileBlockNotificationsWhileDeviceLocked = $policy.AdditionalProperties.workProfileBlockNotificationsWhileDeviceLocked WorkProfileBlockAddingAccounts = $policy.AdditionalProperties.workProfileBlockAddingAccounts WorkProfileBluetoothEnableContactSharing = $policy.AdditionalProperties.workProfileBluetoothEnableContactSharing WorkProfileBlockScreenCapture = $policy.AdditionalProperties.workProfileBlockScreenCapture From eadc0a209c615df3593d59bc8b9c0d0935ccdb36 Mon Sep 17 00:00:00 2001 From: Ricardo Mestre Date: Thu, 8 Feb 2024 15:08:02 +0000 Subject: [PATCH 106/171] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..ff2fbceb0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* IntuneDeviceConfigurationPolicyAndroidWorkProfile + * Fix typo in variable which made it export incorrectly and report that + resource was not in correct state due to testing an incorrect value + FIXES [#3972](https://github.com/microsoft/Microsoft365DSC/issues/3972) + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction From 1199bab0fbd4a5e693c6fef6ec3e444dea7fc095 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 8 Feb 2024 10:36:07 -0500 Subject: [PATCH 107/171] Telemetry Updates --- CHANGELOG.md | 6 ++++++ .../Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 | 9 ++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b0f8be87..2e9e066f89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* MISC + * Telemetry + * Added a new M365DSCTelemetryEventId parameter to track duplication of events. + # 1.24.207.1 * IntuneDeviceEnrollmentPlatformRestriction diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index f9d9554dd2..d05e2419e7 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -5,7 +5,7 @@ This function gets the Application Insights key to be used for storing telemetry .Functionality Internal, Hidden #> -function Get-ApplicationInsightsTelemetryClient +function Get-M365DSCApplicationInsightsTelemetryClient { [CmdletBinding()] param() @@ -53,13 +53,12 @@ function Add-M365DSCTelemetryEvent [System.Collections.Generic.Dictionary[[System.String], [System.Double]]] $Metrics ) - $TelemetryEnabled = [System.Environment]::GetEnvironmentVariable('M365DSCTelemetryEnabled', ` [System.EnvironmentVariableTarget]::Machine) if ($null -eq $TelemetryEnabled -or $TelemetryEnabled -eq $true) { - $TelemetryClient = Get-ApplicationInsightsTelemetryClient + $TelemetryClient = Get-M365DSCApplicationInsightsTelemetryClient try { @@ -207,9 +206,9 @@ function Add-M365DSCTelemetryEvent { Write-Verbose -Message $_ } - + $M365DSCTelemetryEventId = (New-GUID).ToString() + $Data.Add('M365DSCTelemetryEventId', $M365DSCTelemetryEventId) $TelemetryClient.TrackEvent($Type, $Data, $Metrics) - $TelemetryClient.Flush() } catch { From d94baa327e0b5ed3305ffcb7009890c1509b1364 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 8 Feb 2024 20:09:58 -0500 Subject: [PATCH 108/171] TeamsAppSetupPolicy Updates --- CHANGELOG.md | 2 + .../Modules/M365DSCTelemetryEngine.psm1 | 49 ++++++++++++++++--- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 7 ++- 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e9e066f89..ccdbcd5173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ # UNRELEASED +* TeamsAppSetupPolicy + * Changed the logic to retrive arrays of Ids in the Get method. * MISC * Telemetry * Added a new M365DSCTelemetryEventId parameter to track duplication of events. diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index d05e2419e7..9aebe5015d 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -188,26 +188,59 @@ function Add-M365DSCTelemetryEvent [array]$version = (Get-Module 'Microsoft365DSC').Version | Sort-Object -Descending $Data.Add('M365DSCVersion', $version[0].ToString()) - # Get Dependencies loaded versions + # LCM Metadata Information try { - $currentPath = Join-Path -Path $PSScriptRoot -ChildPath '../' -Resolve - $manifest = Import-PowerShellDataFile "$currentPath/Microsoft365DSC.psd1" - $dependencies = $manifest.RequiredModules + $LCMInfo = Get-DscLocalConfigurationManager -ErrorAction Stop - $dependenciesContent = '' - foreach ($dependency in $dependencies) + $certificateConfigured = $false + if (-not [System.String]::IsNullOrEmpty($LCMInfo.CertificateID)) { - $dependenciesContent += Get-Module $dependency.ModuleName | Out-String + $certificateConfigured = $true + } + + $partialConfiguration = $false + if (-not [System.String]::IsNullOrEmpty($LCMInfo.PartialConfigurations)) + { + $partialConfiguration = $true + } + $Data.Add('LCMUsesPartialConfigurations', $partialConfiguration) + $Data.Add('LCMCertificateConfigured', $certificateConfigured) + $Data.Add('LCMConfigurationMode', $LCMInfo.ConfigurationMode) + $Data.Add('LCMConfigurationModeFrequencyMins', $LCMInfo.ConfigurationModeFrequencyMins) + $Data.Add('LCMRefreshMode', $LCMInfo.RefreshMode) + $Data.Add('LCMState', $LCMInfo.LCMState) + $Data.Add('LCMStateDetail', $LCMInfo.LCMStateDetail) + + if ($Global:M365DSCExportInProgress) + { + $Data.Add('M365DSCOperation', 'Export') + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.') + { + $Data.Add('M365DSCOperation', 'MonitoringScheduled') + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') + { + $Data.Add('M365DSCOperation', 'MonitoringManual') + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.') + { + $Data.Add('M365DSCOperation', 'ApplyingConfiguration') + } + else + { + $Data.Add('M365DSCOperation', 'Undetermined') } - $Data.Add('DependenciesVersion', $dependenciesContent) } catch { Write-Verbose -Message $_ } + $M365DSCTelemetryEventId = (New-GUID).ToString() $Data.Add('M365DSCTelemetryEventId', $M365DSCTelemetryEventId) + $TelemetryClient.TrackEvent($Type, $Data, $Metrics) } catch diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index aca92258d4..48033ef43e 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -919,6 +919,7 @@ function Test-M365DSCParameterState } $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues $driftedData.Add('Tenant', $TenantName) + $driftedData.Add('Resource', $source.Split('_')[1]) Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData #endregion $EventMessage.Append(" " + $DriftedParameters.$key + "`r`n") | Out-Null @@ -970,9 +971,6 @@ function Test-M365DSCParameterState -EventID 2 -Source $Source } - #region Telemetry - Add-M365DSCTelemetryEvent -Data $data - #endregion return $returnValue } @@ -1164,7 +1162,7 @@ function Export-M365DSCConfiguration [Switch] $Validate ) - + $Global:M365DSCExportInProgress = $true $Global:MaximumFunctionCount = 32767 # Define the exported resource instances' names Global variable @@ -1348,6 +1346,7 @@ function Export-M365DSCConfiguration # Clear the exported resource instances' names Global variable $Global:M365DSCExportedResourceInstancesNames = $null + $Global:M365DSCExportInProgress = $false } $Script:M365DSCDependenciesValidated = $false From b2bdb5dae8d341708d39eb5b0db46abc2ff4dd1c Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 8 Feb 2024 20:10:33 -0500 Subject: [PATCH 109/171] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccdbcd5173..d5cd322ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ # UNRELEASED * TeamsAppSetupPolicy - * Changed the logic to retrive arrays of Ids in the Get method. + * Changed the logic to retrieve arrays of Ids in the Get method. * MISC * Telemetry * Added a new M365DSCTelemetryEventId parameter to track duplication of events. From f0fe20010bac0a394a2f6136f3ff5727ba166005 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 8 Feb 2024 20:19:37 -0500 Subject: [PATCH 110/171] Adds Current Values to Drift --- CHANGELOG.md | 2 ++ Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5cd322ce7..e04fd295bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * TeamsAppSetupPolicy * Changed the logic to retrieve arrays of Ids in the Get method. * MISC + * Drift Logging + * Now includes the full list of parameters for the current values. * Telemetry * Added a new M365DSCTelemetryEventId parameter to track duplication of events. diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 48033ef43e..d83b9d82c6 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -944,6 +944,17 @@ function Test-M365DSCParameterState $EventMessage.Append(" $Value`r`n") | Out-Null } $EventMessage.Append(" `r`n") | Out-Null + $EventMessage.Append(" `r`n") | Out-Null + foreach ($Key in $CurrentValues.Keys) + { + $Value = $CurrentValues.$Key + if ([System.String]::IsNullOrEmpty($Value)) + { + $Value = "`$null" + } + $EventMessage.Append(" $Value`r`n") | Out-Null + } + $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append('') | Out-Null Add-M365DSCEvent -Message $EventMessage.ToString() -EventType 'Drift' -EntryType 'Warning' ` From 8b6d9c146b23abc589f49d9fbfdfa5b7c06bb817 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 8 Feb 2024 21:02:15 -0500 Subject: [PATCH 111/171] Release 1.24.207.2 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e04fd295bf..fb9ac59df3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.207.2 * TeamsAppSetupPolicy * Changed the logic to retrieve arrays of Ids in the Get method. diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 45bb8020db..b45581ddf2 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-07 +# Generated on: 2024-02-08 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.207.1' + ModuleVersion = '1.24.207.2' # Supported PSEditions # CompatiblePSEditions = @() @@ -140,7 +140,14 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* IntuneDeviceEnrollmentPlatformRestriction + ReleaseNotes = '* TeamsAppSetupPolicy + * Changed the logic to retrieve arrays of Ids in the Get method. + * MISC + * Drift Logging + * Now includes the full list of parameters for the current values. + * Telemetry + * Added a new M365DSCTelemetryEventId parameter to track duplication of events. + * IntuneDeviceEnrollmentPlatformRestriction * Added Priority parameter FIXES [#4081](https://github.com/microsoft/Microsoft365DSC/issues/4081) * SCDLPComplianceRule From b17b6687b6064ca8a5678567bc571cc38a2c95bd Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 09:25:15 -0500 Subject: [PATCH 112/171] Multiple Fixes --- CHANGELOG.md | 6 ++++ ...SFT_AADRoleEligibilityScheduleRequest.psm1 | 10 +++++-- .../MSFT_EXODataClassification.psm1 | 2 +- ...T_IntuneDeviceCompliancePolicyAndroid.psm1 | 2 +- ...iceCompliancePolicyAndroidWorkProfile.psm1 | 2 +- ...IntuneDeviceCompliancePolicyWindows10.psm1 | 2 +- .../MSFT_IntuneDeviceCompliancePolicyiOs.psm1 | 2 +- .../MSFT_SPOUserProfileProperty.psm1 | 29 ++++++++++--------- .../Modules/M365DSCTelemetryEngine.psm1 | 28 ++++++++++++++---- 9 files changed, 57 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb9ac59df3..6ac18a182e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* AADRoleEligibilityScheduleRequest + * Fixed an issue where an error was thrown if no requests were found instead + of simply returning the Null object. + # 1.24.207.2 * TeamsAppSetupPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 index f7becb8603..c5266516d2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleEligibilityScheduleRequest/MSFT_AADRoleEligibilityScheduleRequest.psm1 @@ -182,16 +182,20 @@ $schedule = Get-MgBetaRoleManagementDirectoryRoleEligibilitySchedule -Filter "PrincipalId eq '$PrincipalId' and RoleDefinitionId eq '$RoleDefinitionId'" [Array]$request = Get-MgBetaRoleManagementDirectoryRoleEligibilityScheduleRequest -Filter "PrincipalId eq '$PrincipalId' and RoleDefinitionId eq '$RoleDefinitionId'" | Sort-Object -Property CompletedDateTime -Descending -` $request = $request[0] +` + if ($request.Length -gt 1) + { + $request = $request[0] + } } } else { $ObjectGuid = [System.Guid]::empty if ($PrincipalType -eq 'User') - { + { Write-Verbose -Message "Retrieving principal {$Principal} of type {$PrincipalType}" - + if ([System.Guid]::TryParse($Principal,[System.Management.Automation.PSReference]$ObjectGuid)) { $PrincipalIdValue = Get-MgUser -UserId $Principal -ErrorAction SilentlyContinue diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 index 6b03e06a7d..2754f2074f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 @@ -426,7 +426,7 @@ function Export-TargetResource { $Script:ExportMode = $true #region resource generator code - [array] $Script:exportedInstances = Get-DataClassification -ErrorAction Stop + [array] $Script:exportedInstances = Get-DataClassification -ErrorAction SilentlyContinue $dscContent = [System.Text.StringBuilder]::new() if ($Script:exportedInstances.Length -eq 0) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroid/MSFT_IntuneDeviceCompliancePolicyAndroid.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroid/MSFT_IntuneDeviceCompliancePolicyAndroid.psm1 index 6b3353da1a..39d61be227 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroid/MSFT_IntuneDeviceCompliancePolicyAndroid.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroid/MSFT_IntuneDeviceCompliancePolicyAndroid.psm1 @@ -182,7 +182,7 @@ function Get-TargetResource try { $devicePolicy = Get-MgBetaDeviceManagementDeviceCompliancePolicy ` - -ErrorAction Stop | Where-Object ` + -ErrorAction SilentlyContinue | Where-Object ` -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.androidCompliancePolicy' -and ` $_.displayName -eq $($DisplayName) } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile.psm1 index da9d328933..256d43baf4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile/MSFT_IntuneDeviceCompliancePolicyAndroidWorkProfile.psm1 @@ -172,7 +172,7 @@ function Get-TargetResource try { $devicePolicy = Get-MgBetaDeviceManagementDeviceCompliancePolicy ` - -ErrorAction Stop | Where-Object ` + -ErrorAction SilentlyContinue | Where-Object ` -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.androidWorkProfileCompliancePolicy' -and ` $_.displayName -eq $($DisplayName) } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 index 61399e6146..0e78c8b97a 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyWindows10/MSFT_IntuneDeviceCompliancePolicyWindows10.psm1 @@ -197,7 +197,7 @@ function Get-TargetResource try { $devicePolicy = Get-MgBetaDeviceManagementDeviceCompliancePolicy ` - -ErrorAction Stop | Where-Object ` + -ErrorAction SilentlyContinue | Where-Object ` -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10CompliancePolicy' -and ` $_.displayName -eq $($DisplayName) } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyiOs/MSFT_IntuneDeviceCompliancePolicyiOs.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyiOs/MSFT_IntuneDeviceCompliancePolicyiOs.psm1 index 4e5ccc567a..d9fe71c7a5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyiOs/MSFT_IntuneDeviceCompliancePolicyiOs.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceCompliancePolicyiOs/MSFT_IntuneDeviceCompliancePolicyiOs.psm1 @@ -146,7 +146,7 @@ function Get-TargetResource try { $devicePolicy = Get-MgBetaDeviceManagementDeviceCompliancePolicy ` - -ErrorAction Stop | Where-Object ` + -ErrorAction SilentlyContinue | Where-Object ` -FilterScript { $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.iosCompliancePolicy' -and ` $_.displayName -eq $($DisplayName) } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOUserProfileProperty/MSFT_SPOUserProfileProperty.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOUserProfileProperty/MSFT_SPOUserProfileProperty.psm1 index 05951e4304..4874ead6f7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOUserProfileProperty/MSFT_SPOUserProfileProperty.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOUserProfileProperty/MSFT_SPOUserProfileProperty.psm1 @@ -326,21 +326,24 @@ function Export-TargetResource if ($Results -is [System.Collections.Hashtable] -and $Results.Count -gt 1) { - $Results.Properties = ConvertTo-M365DSCSPOUserProfilePropertyInstanceString -Properties $Results.Properties - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - if ($null -ne $Results.Properties) + if ($Results.Properties) { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Properties' + $Results.Properties = ConvertTo-M365DSCSPOUserProfilePropertyInstanceString -Properties $Results.Properties + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($null -ne $Results.Properties) + { + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'Properties' + } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName Write-Host $Global:M365DSCEmojiGreenCheckMark } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 9aebe5015d..f42225a049 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -245,7 +245,14 @@ function Add-M365DSCTelemetryEvent } catch { - Write-Error $_ + try + { + $TelemetryClient.TrackEvent('Error', $Data, $Metrics) + } + catch + { + Write-Error $_ + } } } } @@ -368,16 +375,27 @@ function Format-M365DSCTelemetryParameters { $data.Add('Resource', $ResourceName) $data.Add('Method', $CommandName) - if (-not $Parameters.ApplicationId) + if ($Parameters.Credential) { - $data.Add('Principal', $Parameters.Credential.UserName) - $data.Add('TenantId', $Parameters.Credential.UserName.Split('@')[1]) + try + { + $data.Add('Principal', $Parameters.Credential.UserName) + $data.Add('TenantId', $Parameters.Credential.UserName.Split('@')[1]) + } + catch + { + Write-Verbose -Message $_ + } } - else + elseif ($Parameters.ApplicationId) { $data.Add('Principal', $Parameters.ApplicationId) $data.Add('TenantId', $Parameters.TenantId) } + elseif (-not [System.String]::IsNullOrEmpty($TenantId)) + { + $data.Add('TenantId', $Parameters.TenantId) + } $data.Add('ConnectionMode', (Get-M365DSCAuthenticationMode -Parameters $Parameters)) } catch From 0826bc7a5ff9b579a8900b1e8b76e1ff6eb3aec2 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 11:25:36 -0500 Subject: [PATCH 113/171] Update Global - Integration - EXO.yml --- .github/workflows/Global - Integration - EXO.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/Global - Integration - EXO.yml b/.github/workflows/Global - Integration - EXO.yml index 4957ccddcd..5635138bd5 100644 --- a/.github/workflows/Global - Integration - EXO.yml +++ b/.github/workflows/Global - Integration - EXO.yml @@ -6,6 +6,8 @@ jobs: # The type of runner that the job will run on runs-on: windows-latest + permissions: write + # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' From 25261909dd8db5d62d2bd4da7db1e710c74581d7 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 12:05:08 -0500 Subject: [PATCH 114/171] Update Global - Integration - EXO.yml --- .github/workflows/Global - Integration - EXO.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Global - Integration - EXO.yml b/.github/workflows/Global - Integration - EXO.yml index 5635138bd5..76b0ce03bc 100644 --- a/.github/workflows/Global - Integration - EXO.yml +++ b/.github/workflows/Global - Integration - EXO.yml @@ -6,7 +6,7 @@ jobs: # The type of runner that the job will run on runs-on: windows-latest - permissions: write + permissions: write-all # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' From c77943a7e0eb050127d2c73b0e969be75d4f59b1 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 9 Feb 2024 17:08:07 +0000 Subject: [PATCH 115/171] Updated {Create} EXO Integration Tests --- .../M365DSCIntegration.EXO.Create.Tests.ps1 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 8ae6b2b387..59fb6f90f8 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -654,6 +654,15 @@ Ensure = "Present" Credential = $Credscredential } + EXORecipientPermission 'AddSendAs' + { + + Identity = 'AdeleV@$Domain' + Trustee = "admin@$Domain" + AccessRights = 'SendAs' + Ensure = 'Present' + Credential = $Credscredential + } EXORemoteDomain '583b0b70-b45d-401f-98a6-0e7fa8434946' { Identity = "Integration" From afdb1a87ffcffc433cab012bdaefff080c67724a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 12:17:37 -0500 Subject: [PATCH 116/171] Update 1-Create.ps1 --- .../Examples/Resources/EXORecipientPermission/1-Create.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 index 8df472f8f0..6b6c1e6190 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 @@ -20,8 +20,7 @@ Configuration Example { EXORecipientPermission 'AddSendAs' { - - Identity = 'AdeleV@$Domain' + Identity = "AlexW@$Domain" Trustee = "admin@$Domain" AccessRights = 'SendAs' Ensure = 'Present' From ff4ab235d91eb84e1534d472810ecc37ad397db8 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 9 Feb 2024 17:20:06 +0000 Subject: [PATCH 117/171] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 59fb6f90f8..4dd7a69343 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -656,8 +656,7 @@ } EXORecipientPermission 'AddSendAs' { - - Identity = 'AdeleV@$Domain' + Identity = "AlexW@$Domain" Trustee = "admin@$Domain" AccessRights = 'SendAs' Ensure = 'Present' From aea26112d1bd3362cda4f072c0108b4abfa5cace Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 12:22:47 -0500 Subject: [PATCH 118/171] Updated Graph Dependencies to 2.13.1 --- .../workflows/Global - Integration - AAD.yml | 2 ++ .../Global - Integration - INTUNE.yml | 2 ++ .github/workflows/PublishGitHubPages.yml | 2 ++ .github/workflows/Unit Tests.yml | 2 ++ CHANGELOG.md | 2 ++ .../Dependencies/Manifest.psd1 | 34 +++++++++---------- .../EXORecipientPermission/1-Create.ps1 | 3 +- 7 files changed, 28 insertions(+), 19 deletions(-) diff --git a/.github/workflows/Global - Integration - AAD.yml b/.github/workflows/Global - Integration - AAD.yml index 7f681f74d9..df54194a4b 100644 --- a/.github/workflows/Global - Integration - AAD.yml +++ b/.github/workflows/Global - Integration - AAD.yml @@ -6,6 +6,8 @@ jobs: # The type of runner that the job will run on runs-on: windows-latest + permissions: write-all + # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' diff --git a/.github/workflows/Global - Integration - INTUNE.yml b/.github/workflows/Global - Integration - INTUNE.yml index 89b45a7056..1582b1b061 100644 --- a/.github/workflows/Global - Integration - INTUNE.yml +++ b/.github/workflows/Global - Integration - INTUNE.yml @@ -6,6 +6,8 @@ jobs: # The type of runner that the job will run on runs-on: windows-latest + permissions: write-all + # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' diff --git a/.github/workflows/PublishGitHubPages.yml b/.github/workflows/PublishGitHubPages.yml index f0cee1a374..bf85a3d7be 100644 --- a/.github/workflows/PublishGitHubPages.yml +++ b/.github/workflows/PublishGitHubPages.yml @@ -8,6 +8,8 @@ jobs: GenerateResource: runs-on: windows-latest + permissions: write-all + # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' diff --git a/.github/workflows/Unit Tests.yml b/.github/workflows/Unit Tests.yml index 103e67b01c..a636b3093d 100644 --- a/.github/workflows/Unit Tests.yml +++ b/.github/workflows/Unit Tests.yml @@ -7,6 +7,8 @@ jobs: # The type of runner that the job will run on runs-on: windows-latest + permissions: write-all + # Only when run from the main repo if: github.repository == 'microsoft/Microsoft365DSC' diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ac18a182e..0f45b39e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. +* DEPENDENCIES + * Updated Microsoft.Graph dependencies to version 2.13.1. # 1.24.207.2 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 6c1877c352..5c97f552db 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -10,71 +10,71 @@ }, @{ ModuleName = 'Microsoft.Graph.Applications' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Authentication' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Enrollment' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.Governance' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Reports' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement.Administration' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DirectoryObjects' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Groups' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Planner' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Users' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.Graph.Users.Actions' - RequiredVersion = '2.12.0' + RequiredVersion = '2.13.1' }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 index 8df472f8f0..6b6c1e6190 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORecipientPermission/1-Create.ps1 @@ -20,8 +20,7 @@ Configuration Example { EXORecipientPermission 'AddSendAs' { - - Identity = 'AdeleV@$Domain' + Identity = "AlexW@$Domain" Trustee = "admin@$Domain" AccessRights = 'SendAs' Ensure = 'Present' From 70c3a4b78602d95989ddc89cb13f05375c514038 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 9 Feb 2024 17:23:54 +0000 Subject: [PATCH 119/171] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index 25081b9bf3..b944ef9129 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -125,13 +125,6 @@ Ensure = "Present" Credential = $Credscredential } - EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' - { - UserName = "AdeleV@$Domain" - AuthenticationPolicyName = "Test Policy" # Updaqted Property - Ensure = "Present" - Credential = $Credscredential - } EXOAvailabilityAddressSpace 'ConfigureAvailabilityAddressSpace' { Identity = 'Contoso.com' @@ -174,7 +167,7 @@ EnforceSchedulingHorizon = $True; Ensure = "Present"; ForwardRequestsToDelegates = $True; - Identity = "AdeleV"; + Identity = "admin@$Domain"; MaximumConflictInstances = 0; MaximumDurationInMinutes = 1440; MinimumDurationInMinutes = 0; @@ -206,10 +199,10 @@ ActiveSyncBlockedDeviceIDs = @() ActiveSyncDebugLogging = $False ActiveSyncEnabled = $True - ActiveSyncMailboxPolicy = 'Demo EXO Mobile Device Policy Default' + ActiveSyncMailboxPolicy = 'Default' ActiveSyncSuppressReadReceipt = $False EwsEnabled = $True - Identity = 'AdeleV' + Identity = "admin@$Domain" ImapEnabled = $True # Updated Property ImapForceICalForCalendarRetrievalOption = $False ImapMessagesRetrievalMimeFormat = 'BestBodyFormat' @@ -220,7 +213,7 @@ OutlookMobileEnabled = $True OWAEnabled = $True OWAforDevicesEnabled = $True - OwaMailboxPolicy = 'OwaMailboxPolicy-Default' + OwaMailboxPolicy = 'OwaMailboxPolicy-Integration' PopEnabled = $False PopForceICalForCalendarRetrievalOption = $True PopMessagesRetrievalMimeFormat = 'BestBodyFormat' @@ -296,8 +289,8 @@ Name = "Integration Policy" EnabledEmailAddressTemplates = @("SMTP:@$Domain") EnabledPrimarySMTPAddressTemplate = "@$Domain" - ManagedByFilter = "" - Priority = 2 # Updated Property + ManagedByFilter = "Department -eq 'Sales'" # Updated Property + Priority = 1 Ensure = "Present" Credential = $Credscredential } @@ -312,7 +305,7 @@ } EXOGroupSettings 'TestGroup' { - DisplayName = "Test Group"; + DisplayName = "All Company"; AccessType = "Public"; AlwaysSubscribeMembersToCalendarEvents = $False; AuditLogAgeLimit = "90.00:00:00"; @@ -483,12 +476,12 @@ CreateOOFEvent = $False; Credential = $Credscredential; DeclineAllEventsForScheduledOOF = $False; - DeclineEventsForScheduledOOF = $True; # Updated Property + DeclineEventsForScheduledOOF = $False; DeclineMeetingMessage = ""; EndTime = "1/23/2024 3:00:00 PM"; Ensure = "Present"; ExternalAudience = "All"; - ExternalMessage = ""; + ExternalMessage = (New-Guid).ToString(); # Updated Property Identity = "AdeleV@$Domain"; InternalMessage = ""; OOFEventSubject = ""; @@ -499,7 +492,7 @@ Credential = $credsCredential; DetailLevel = "AvailabilityOnly"; Ensure = "Present"; - Identity = "AdeleV:\Calendar"; + Identity = "AlexW@$Domain" + ":\Calendar"; PublishDateRangeFrom = "ThreeMonths"; PublishDateRangeTo = "ThreeMonths"; PublishEnabled = $True; # Updated Property @@ -511,7 +504,7 @@ Credential = $credsCredential; Deny = $True; # Updated Property Ensure = "Present"; - Identity = "AdeleV"; + Identity = "AlexW@$Domain"; InheritanceType = "All"; User = "NT AUTHORITY\SELF"; } From 1944836a403ce49d22c809078a1a8efb3c55f720 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Fri, 9 Feb 2024 17:51:31 +0000 Subject: [PATCH 120/171] Updated Resources and Cmdlet documentation pages --- .../EXOAuthenticationPolicyAssignment.md | 27 ----- .../exchange/EXOCASMailboxSettings.md | 7 +- .../exchange/EXOCalendarProcessing.md | 2 +- .../exchange/EXOEmailAddressPolicy.md | 4 +- .../resources/exchange/EXOGroupSettings.md | 2 +- .../EXOMailboxAutoReplyConfiguration.md | 4 +- .../exchange/EXOMailboxCalendarFolder.md | 3 +- .../exchange/EXOMailboxPermission.md | 3 +- .../exchange/EXOOfflineAddressBook.md | 1 - .../exchange/EXORecipientPermission.md | 102 ++++++++++++++++++ ...tuneDeviceEnrollmentPlatformRestriction.md | 1 + .../teams/TeamsUserCallingSettings.md | 5 +- 12 files changed, 121 insertions(+), 40 deletions(-) create mode 100644 docs/docs/resources/exchange/EXORecipientPermission.md diff --git a/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md b/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md index 498c4d50bf..62a9c78606 100644 --- a/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md +++ b/docs/docs/resources/exchange/EXOAuthenticationPolicyAssignment.md @@ -65,33 +65,6 @@ Configuration Example ### Example 2 -```powershell -Configuration Example -{ - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential - ) - Import-DscResource -ModuleName Microsoft365DSC - - $Domain = $Credscredential.Username.Split('@')[1] - node localhost - { - EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' - { - UserName = "AdeleV@$Domain" - AuthenticationPolicyName = "Test Policy" # Updaqted Property - Ensure = "Present" - Credential = $Credscredential - } - } -} -``` - -### Example 3 - - ```powershell Configuration Example { diff --git a/docs/docs/resources/exchange/EXOCASMailboxSettings.md b/docs/docs/resources/exchange/EXOCASMailboxSettings.md index d4453b4317..ee6c197d18 100644 --- a/docs/docs/resources/exchange/EXOCASMailboxSettings.md +++ b/docs/docs/resources/exchange/EXOCASMailboxSettings.md @@ -85,6 +85,7 @@ Configuration Example Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOCASMailboxSettings 'AdeleVCasMailboxSettings' @@ -93,10 +94,10 @@ Configuration Example ActiveSyncBlockedDeviceIDs = @() ActiveSyncDebugLogging = $False ActiveSyncEnabled = $True - ActiveSyncMailboxPolicy = 'Demo EXO Mobile Device Policy Default' + ActiveSyncMailboxPolicy = 'Default' ActiveSyncSuppressReadReceipt = $False EwsEnabled = $True - Identity = 'AdeleV' + Identity = "admin@$Domain" ImapEnabled = $True # Updated Property ImapForceICalForCalendarRetrievalOption = $False ImapMessagesRetrievalMimeFormat = 'BestBodyFormat' @@ -107,7 +108,7 @@ Configuration Example OutlookMobileEnabled = $True OWAEnabled = $True OWAforDevicesEnabled = $True - OwaMailboxPolicy = 'OwaMailboxPolicy-Default' + OwaMailboxPolicy = 'OwaMailboxPolicy-Integration' PopEnabled = $False PopForceICalForCalendarRetrievalOption = $True PopMessagesRetrievalMimeFormat = 'BestBodyFormat' diff --git a/docs/docs/resources/exchange/EXOCalendarProcessing.md b/docs/docs/resources/exchange/EXOCalendarProcessing.md index 39eb464dec..009995378e 100644 --- a/docs/docs/resources/exchange/EXOCalendarProcessing.md +++ b/docs/docs/resources/exchange/EXOCalendarProcessing.md @@ -117,7 +117,7 @@ Configuration Example EnforceSchedulingHorizon = $True; Ensure = "Present"; ForwardRequestsToDelegates = $True; - Identity = "AdeleV"; + Identity = "admin@$Domain"; MaximumConflictInstances = 0; MaximumDurationInMinutes = 1440; MinimumDurationInMinutes = 0; diff --git a/docs/docs/resources/exchange/EXOEmailAddressPolicy.md b/docs/docs/resources/exchange/EXOEmailAddressPolicy.md index 5fe66dd421..10e9f6b5d6 100644 --- a/docs/docs/resources/exchange/EXOEmailAddressPolicy.md +++ b/docs/docs/resources/exchange/EXOEmailAddressPolicy.md @@ -93,8 +93,8 @@ Configuration Example Name = "Integration Policy" EnabledEmailAddressTemplates = @("SMTP:@$Domain") EnabledPrimarySMTPAddressTemplate = "@$Domain" - ManagedByFilter = "" - Priority = 2 # Updated Property + ManagedByFilter = "Department -eq 'Sales'" # Updated Property + Priority = 1 Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOGroupSettings.md b/docs/docs/resources/exchange/EXOGroupSettings.md index beb5db2d4f..f9ddf2d3bd 100644 --- a/docs/docs/resources/exchange/EXOGroupSettings.md +++ b/docs/docs/resources/exchange/EXOGroupSettings.md @@ -106,7 +106,7 @@ Configuration Example { EXOGroupSettings 'TestGroup' { - DisplayName = "Test Group"; + DisplayName = "All Company"; AccessType = "Public"; AlwaysSubscribeMembersToCalendarEvents = $False; AuditLogAgeLimit = "90.00:00:00"; diff --git a/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md b/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md index 5357252f4a..d976f09127 100644 --- a/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md +++ b/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md @@ -72,12 +72,12 @@ Configuration Example CreateOOFEvent = $False; Credential = $Credscredential; DeclineAllEventsForScheduledOOF = $False; - DeclineEventsForScheduledOOF = $True; # Updated Property + DeclineEventsForScheduledOOF = $False; DeclineMeetingMessage = ""; EndTime = "1/23/2024 3:00:00 PM"; Ensure = "Present"; ExternalAudience = "All"; - ExternalMessage = ""; + ExternalMessage = (New-Guid).ToString(); # Updated Property Identity = "AdeleV@$Domain"; InternalMessage = ""; OOFEventSubject = ""; diff --git a/docs/docs/resources/exchange/EXOMailboxCalendarFolder.md b/docs/docs/resources/exchange/EXOMailboxCalendarFolder.md index 1f491c98a5..cbbfc603e7 100644 --- a/docs/docs/resources/exchange/EXOMailboxCalendarFolder.md +++ b/docs/docs/resources/exchange/EXOMailboxCalendarFolder.md @@ -57,6 +57,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOMailboxCalendarFolder "JohnCalendarFolder" @@ -64,7 +65,7 @@ Configuration Example Credential = $credsCredential; DetailLevel = "AvailabilityOnly"; Ensure = "Present"; - Identity = "AdeleV:\Calendar"; + Identity = "AlexW@$Domain" + ":\Calendar"; PublishDateRangeFrom = "ThreeMonths"; PublishDateRangeTo = "ThreeMonths"; PublishEnabled = $True; # Updated Property diff --git a/docs/docs/resources/exchange/EXOMailboxPermission.md b/docs/docs/resources/exchange/EXOMailboxPermission.md index 4fec5d4340..9e9a8da182 100644 --- a/docs/docs/resources/exchange/EXOMailboxPermission.md +++ b/docs/docs/resources/exchange/EXOMailboxPermission.md @@ -54,6 +54,7 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOMailboxPermission "TestPermission" @@ -62,7 +63,7 @@ Configuration Example Credential = $credsCredential; Deny = $True; # Updated Property Ensure = "Present"; - Identity = "AdeleV"; + Identity = "AlexW@$Domain"; InheritanceType = "All"; User = "NT AUTHORITY\SELF"; } diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index cdadd9da05..cb89dae984 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -93,7 +93,6 @@ Configuration Example { Name = "Integration Address Book" AddressLists = @('\Offline Global Address List') - ConfiguredAttributes = @('OfficeLocation, ANR','ProxyAddresses, ANR','PhoneticGivenName, ANR','GivenName, ANR','PhoneticSurname, ANR','Surname, ANR','Account, ANR','PhoneticDisplayName, ANR','ExternalDirectoryObjectId, Value','ExternalMemberCount, Value','TotalMemberCount, Value','ModerationEnabled, Value','MailboxGuid, Value','DelivContLength, Value','MailTipTranslations, Value','ObjectGuid, Value','DisplayTypeEx, Value','DisplayNamePrintableAnsi, Value','HomeMdbA, Value','Certificate, Value','UserSMimeCertificate, Value','UserCertificate, Value','Comment, Value','PagerTelephoneNumber, Value','AssistantTelephoneNumber, Value','MobileTelephoneNumber, Value','PrimaryFaxNumber, Value','Home2TelephoneNumberMv, Value','Business2TelephoneNumberMv, Value','HomeTelephoneNumber, Value','TargetAddress, Value','PhoneticDepartmentName, Value','DepartmentName, Value','Assistant, Value','PhoneticCompanyName, Value','CompanyName, Value','Title, Value','Country, Value','PostalCode, Value','StateOrProvince, Value','Locality, Value','StreetAddress, Value','Initials, Value','BusinessTelephoneNumber, Value','SendRichInfo, Value','ObjectType, Value','DisplayType, Value','RejectMessagesFromDLMembers, Indicator','AcceptMessagesOnlyFromDLMembers, Indicator','RejectMessagesFrom, Indicator','AcceptMessagesOnlyFrom, Indicator','UmSpokenName, Indicator','ThumbnailPhoto, Indicator') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" diff --git a/docs/docs/resources/exchange/EXORecipientPermission.md b/docs/docs/resources/exchange/EXORecipientPermission.md new file mode 100644 index 0000000000..3d959b534d --- /dev/null +++ b/docs/docs/resources/exchange/EXORecipientPermission.md @@ -0,0 +1,102 @@ +# EXORecipientPermission + +## Parameters + +| Parameter | Attribute | DataType | Description | Allowed Values | +| --- | --- | --- | --- | --- | +| **Identity** | Key | String | The mailbox the permission should be given on. | | +| **Trustee** | Key | String | The account to give the permission to. | | +| **AccessRights** | Write | StringArray[] | The access rights granted to the account. Only 'SendAs' is supported. | | +| **Ensure** | Write | String | Present ensures the group exists, absent ensures it is removed | `Present`, `Absent` | +| **Credential** | Write | PSCredential | Credentials of the Exchange Global Admin | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Id of the Azure Active Directory tenant used for authentication. | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | +| **CertificatePassword** | Write | PSCredential | Username can be made up to anything but password will be used for CertificatePassword | | +| **CertificatePath** | Write | String | Path to certificate used in service principal usually a PFX file. | | +| **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | + +## Description + +This resource allows users to retrieve Office 365 Recipient Permissions. + +## Permissions + +### Exchange + +To authenticate with Microsoft Exchange, this resource required the following permissions: + +#### Roles + +- Mail Enabled Public Folders, MyName, Public Folders, Compliance Admin, User Options, Message Tracking, View-Only Recipients, Role Management, Legal Hold, Audit Logs, Retention Management, Distribution Groups, Move Mailboxes, Information Rights Management, Mail Recipient Creation, Reset Password, View-Only Audit Logs, Mail Recipients, Mailbox Search, UM Mailboxes, Security Group Creation and Membership, Mailbox Import Export, MyMailboxDelegation, MyDisplayName + +#### Role Groups + +- Organization Management + +## Examples + +### Example 1 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + $Domain = $Credscredential.Username.Split('@')[1] + node localhost + { + EXORecipientPermission 'AddSendAs' + { + Identity = "AlexW@$Domain" + Trustee = "admin@$Domain" + AccessRights = 'SendAs' + Ensure = 'Present' + Credential = $Credscredential + } + } +} +``` + +### Example 2 + +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. + +```powershell +Configuration Example +{ + param + ( + [Parameter(Mandatory = $true)] + [PSCredential] + $Credscredential + ) + + Import-DscResource -ModuleName Microsoft365DSC + + $Domain = $Credscredential.Username.Split('@')[1] + node localhost + { + EXORecipientPermission 'AddSendAs' + { + + Identity = 'AdeleV@$Domain' + Trustee = "admin@$Domain" + Ensure = 'Absent' + Credential = $Credscredential + } + } +} +``` + diff --git a/docs/docs/resources/intune/IntuneDeviceEnrollmentPlatformRestriction.md b/docs/docs/resources/intune/IntuneDeviceEnrollmentPlatformRestriction.md index 603b856830..cce07b5e29 100644 --- a/docs/docs/resources/intune/IntuneDeviceEnrollmentPlatformRestriction.md +++ b/docs/docs/resources/intune/IntuneDeviceEnrollmentPlatformRestriction.md @@ -17,6 +17,7 @@ | **MacRestriction** | Write | MSFT_DeviceEnrollmentPlatformRestriction | Mac restrictions based on platform, platform operating system version, and device ownership. | | | **MacOSRestriction** | Write | MSFT_DeviceEnrollmentPlatformRestriction | Mac OS restrictions based on platform, platform operating system version, and device ownership. | | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Assignments of the policy. | | +| **Priority** | Write | UInt32 | Priority is used when a user exists in multiple groups that are assigned enrollment configuration. Users are subject only to the configuration with the lowest priority value. Inherited from deviceEnrollmentConfiguration. | | | **Ensure** | Write | String | Present ensures the restriction exists, absent ensures it is removed. | `Present`, `Absent` | | **Credential** | Write | PSCredential | Credentials of the Intune Admin | | | **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | diff --git a/docs/docs/resources/teams/TeamsUserCallingSettings.md b/docs/docs/resources/teams/TeamsUserCallingSettings.md index 369c7b6078..4dd57c90d4 100644 --- a/docs/docs/resources/teams/TeamsUserCallingSettings.md +++ b/docs/docs/resources/teams/TeamsUserCallingSettings.md @@ -17,7 +17,10 @@ | **ForwardingTargetType** | Write | String | The forwarding target type. Supported values are Voicemail, SingleTarget, MyDelegates and Group. Voicemail is only supported for Immediate forwarding. | `Group`, `MyDelegates`, `SingleTarget`, `Voicemail` | | **ForwardingTarget** | Write | String | The forwarding target. Supported types of values are ObjectId's, SIP addresses and phone numbers. For phone numbers we support the following types of formats: E.164 (+12065551234 or +1206555000;ext=1234) or non-E.164 like 1234. | | | **Ensure** | Write | String | Present ensures the policy exists, absent ensures it is removed. | `Present`, `Absent` | -| **Credential** | Required | PSCredential | Credentials of the Teams Global Admin. | | +| **Credential** | Write | PSCredential | Credentials of the Teams Global Admin. | | +| **ApplicationId** | Write | String | Id of the Azure Active Directory application to authenticate with. | | +| **TenantId** | Write | String | Name of the Azure Active Directory tenant used for authentication. Format contoso.onmicrosoft.com | | +| **CertificateThumbprint** | Write | String | Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication. | | | **ManagedIdentity** | Write | Boolean | Managed ID being used for authentication. | | From 351c5c68c07db6e3655314e79542ff36be734495 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Fri, 9 Feb 2024 15:05:29 -0500 Subject: [PATCH 121/171] Fixes Integration Tests --- CHANGELOG.md | 3 +++ .../MSFT_EXOMobileDeviceMailboxPolicy.psm1 | 1 + .../Examples/Resources/EXOMailboxPlan/2-Update.ps1 | 6 +++--- .../Resources/EXOMailboxSettings/2-Update.ps1 | 2 +- .../Resources/EXOOfflineAddressBook/1-Create.ps1 | 2 +- .../Resources/EXOOfflineAddressBook/2-Update.ps1 | 2 +- .../EXOOnPremisesOrganization/2-Update.ps1 | 14 +++++++------- .../Resources/EXOPartnerApplication/1-Create.ps1 | 1 + .../Resources/EXOPartnerApplication/2-Update.ps1 | 3 ++- .../EXOPerimeterConfiguration/2-Update.ps1 | 2 +- .../Resources/EXOQuarantinePolicy/1-Create.ps1 | 2 +- .../Resources/EXOQuarantinePolicy/2-Update.ps1 | 2 +- .../Resources/EXOQuarantinePolicy/3-Remove.ps1 | 2 +- .../Resources/EXORemoteDomain/2-Update.ps1 | 4 ++-- .../Resources/EXORoleAssignmentPolicy/2-Update.ps1 | 4 ++-- 15 files changed, 28 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f45b39e95..3f0e77a756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. +* EXOMobileDeviceMailboxPolicy + * Fixes an issue where an empty MinPasswordLength value was always passed down + to the update logic flow. * DEPENDENCIES * Updated Microsoft.Graph dependencies to version 2.13.1. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMobileDeviceMailboxPolicy/MSFT_EXOMobileDeviceMailboxPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMobileDeviceMailboxPolicy/MSFT_EXOMobileDeviceMailboxPolicy.psm1 index 870613162f..1b4cb79f54 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMobileDeviceMailboxPolicy/MSFT_EXOMobileDeviceMailboxPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMobileDeviceMailboxPolicy/MSFT_EXOMobileDeviceMailboxPolicy.psm1 @@ -739,6 +739,7 @@ function Set-TargetResource if ([System.String]::IsNullOrEmpty($MinPasswordLength)) { $NewMobileDeviceMailboxPolicyParams.Remove('MinPasswordLength') | Out-Null + $SetMobileDeviceMailboxPolicyParams.Remove('MinPasswordLength') | Out-Null } # CASE: Mobile Device Mailbox Policy doesn't exist but should; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPlan/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPlan/2-Update.ps1 index 998d3222d6..280e394098 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPlan/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxPlan/2-Update.ps1 @@ -17,11 +17,11 @@ Configuration Example EXOMailboxPlan 'ConfigureMailboxPlan' { Ensure = "Present"; - Identity = "Integration Plan"; - IssueWarningQuota = "98 GB (105,226,698,752 bytes)"; + Identity = "ExchangeOnlineEssentials"; + IssueWarningQuota = "15 GB (16,106,127,360 bytes)"; MaxReceiveSize = "25 MB (26,214,400 bytes)"; MaxSendSize = "25 MB (26,214,400 bytes)"; - ProhibitSendQuota = "99 GB (106,300,440,576 bytes)"; + ProhibitSendQuota = "15 GB (16,106,127,360 bytes)"; ProhibitSendReceiveQuota = "15 GB (16,106,127,360 bytes)"; # Updated Property RetainDeletedItemsFor = "14.00:00:00"; RoleAssignmentPolicy = "Default Role Assignment Policy"; diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxSettings/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxSettings/2-Update.ps1 index 91d0da31c2..7d1ec97214 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxSettings/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOMailboxSettings/2-Update.ps1 @@ -18,7 +18,7 @@ Configuration Example { EXOMailboxSettings 'OttawaTeamMailboxSettings' { - DisplayName = 'Ottawa Employees' + DisplayName = 'Conf Room Adams' TimeZone = 'Eastern Standard Time' Locale = 'en-US' # Updated Property Ensure = 'Present' diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 index d59a79deae..01477e3204 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/1-Create.ps1 @@ -19,7 +19,7 @@ Configuration Example EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 index 3a05445e78..0fe9391578 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOfflineAddressBook/2-Update.ps1 @@ -19,7 +19,7 @@ Configuration Example EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/2-Update.ps1 index 8f94e907b8..da8b029d11 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOOnPremisesOrganization/2-Update.ps1 @@ -18,13 +18,13 @@ Configuration Example { EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' - Comment = 'Mail for Contoso. Updated' # Updated Property - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + Identity = 'Integration' + Comment = 'Mail for Contoso - Updated' #Updated Property + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 index a70e94d02c..f90d243abe 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/1-Create.ps1 @@ -19,6 +19,7 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" + AcceptSecurityIdentifierInformation = $true Enabled = $True Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 index a38a41068b..bf09619125 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPartnerApplication/2-Update.ps1 @@ -19,7 +19,8 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - Enabled = $False # Updated Property + AcceptSecurityIdentifierInformation = $False # Updated Property + Enabled = $True Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOPerimeterConfiguration/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOPerimeterConfiguration/2-Update.ps1 index 6f4a9e1640..7a7f729945 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOPerimeterConfiguration/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOPerimeterConfiguration/2-Update.ps1 @@ -18,7 +18,7 @@ Configuration Example EXOPerimeterConfiguration 'ConfigurePerimeterConfiguration' { IsSingleInstance = 'Yes' - GatewayIPAddresses = '123.0.0.1' + #GatewayIPAddresses = '123.0.0.1' Ensure = 'Present' Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/1-Create.ps1 index 03e8295d46..3acd8f9215 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/1-Create.ps1 @@ -20,7 +20,7 @@ Configuration Example { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $False; - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/2-Update.ps1 index feb94715b4..6c5a45c055 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/2-Update.ps1 @@ -20,7 +20,7 @@ Configuration Example { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $True; # Updated Property - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/3-Remove.ps1 index 0281fc3468..bc6b68e50e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOQuarantinePolicy/3-Remove.ps1 @@ -18,7 +18,7 @@ Configuration Example { EXOQuarantinePolicy 'ConfigureQuarantinePolicy' { - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Absent" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 index 22d9d7249d..109dc72855 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORemoteDomain/2-Update.ps1 @@ -27,9 +27,9 @@ Configuration Example DisplaySenderName = $True DomainName = "contoso.com" IsInternal = $False - LineWrapSize = "Integration" + LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXORoleAssignmentPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXORoleAssignmentPolicy/2-Update.ps1 index 7005a4835f..b9166d8e45 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXORoleAssignmentPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXORoleAssignmentPolicy/2-Update.ps1 @@ -17,8 +17,8 @@ Configuration Example EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" - Description = "This policy grants end users the permission to set their options in Outlook on the web and perform other self-administration tasks." - IsDefault = $False # Updated Property + Description = "Updated Description" # Updated Property + IsDefault = $True Roles = @("My Marketplace Apps","MyVoiceMail","MyDistributionGroups","MyRetentionPolicies","MyContactInformation","MyBaseOptions","MyTextMessaging","MyDistributionGroupMembership","MyProfileInformation","My Custom Apps","My ReadWriteMailbox Apps") Ensure = "Present" Credential = $Credscredential From 3daba2e4648ea3e22b481c300be454441f0bf16f Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 10 Feb 2024 14:38:47 +0000 Subject: [PATCH 122/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOMailboxPlan.md | 6 +++--- docs/docs/resources/exchange/EXOMailboxSettings.md | 2 +- .../resources/exchange/EXOOfflineAddressBook.md | 4 ++-- .../exchange/EXOOnPremisesOrganization.md | 14 +++++++------- .../resources/exchange/EXOPartnerApplication.md | 4 +++- .../exchange/EXOPerimeterConfiguration.md | 2 +- .../docs/resources/exchange/EXOQuarantinePolicy.md | 6 +++--- docs/docs/resources/exchange/EXORemoteDomain.md | 4 ++-- .../resources/exchange/EXORoleAssignmentPolicy.md | 4 ++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/docs/docs/resources/exchange/EXOMailboxPlan.md b/docs/docs/resources/exchange/EXOMailboxPlan.md index a73658b8ad..a71b4df323 100644 --- a/docs/docs/resources/exchange/EXOMailboxPlan.md +++ b/docs/docs/resources/exchange/EXOMailboxPlan.md @@ -62,11 +62,11 @@ Configuration Example EXOMailboxPlan 'ConfigureMailboxPlan' { Ensure = "Present"; - Identity = "Integration Plan"; - IssueWarningQuota = "98 GB (105,226,698,752 bytes)"; + Identity = "ExchangeOnlineEssentials"; + IssueWarningQuota = "15 GB (16,106,127,360 bytes)"; MaxReceiveSize = "25 MB (26,214,400 bytes)"; MaxSendSize = "25 MB (26,214,400 bytes)"; - ProhibitSendQuota = "99 GB (106,300,440,576 bytes)"; + ProhibitSendQuota = "15 GB (16,106,127,360 bytes)"; ProhibitSendReceiveQuota = "15 GB (16,106,127,360 bytes)"; # Updated Property RetainDeletedItemsFor = "14.00:00:00"; RoleAssignmentPolicy = "Default Role Assignment Policy"; diff --git a/docs/docs/resources/exchange/EXOMailboxSettings.md b/docs/docs/resources/exchange/EXOMailboxSettings.md index 13089584c9..cefefccc2b 100644 --- a/docs/docs/resources/exchange/EXOMailboxSettings.md +++ b/docs/docs/resources/exchange/EXOMailboxSettings.md @@ -60,7 +60,7 @@ Configuration Example { EXOMailboxSettings 'OttawaTeamMailboxSettings' { - DisplayName = 'Ottawa Employees' + DisplayName = 'Conf Room Adams' TimeZone = 'Eastern Standard Time' Locale = 'en-US' # Updated Property Ensure = 'Present' diff --git a/docs/docs/resources/exchange/EXOOfflineAddressBook.md b/docs/docs/resources/exchange/EXOOfflineAddressBook.md index cb89dae984..fa73a78e70 100644 --- a/docs/docs/resources/exchange/EXOOfflineAddressBook.md +++ b/docs/docs/resources/exchange/EXOOfflineAddressBook.md @@ -60,7 +60,7 @@ Configuration Example EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" @@ -92,7 +92,7 @@ Configuration Example EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" diff --git a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md index 9a5dcd5078..c99234621e 100644 --- a/docs/docs/resources/exchange/EXOOnPremisesOrganization.md +++ b/docs/docs/resources/exchange/EXOOnPremisesOrganization.md @@ -116,13 +116,13 @@ Configuration Example { EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' - Comment = 'Mail for Contoso. Updated' # Updated Property - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + Identity = 'Integration' + Comment = 'Mail for Contoso - Updated' #Updated Property + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOPartnerApplication.md b/docs/docs/resources/exchange/EXOPartnerApplication.md index e7830f4f35..ef140ee08c 100644 --- a/docs/docs/resources/exchange/EXOPartnerApplication.md +++ b/docs/docs/resources/exchange/EXOPartnerApplication.md @@ -61,6 +61,7 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" + AcceptSecurityIdentifierInformation = $true Enabled = $True Ensure = "Present" Credential = $Credscredential @@ -91,7 +92,8 @@ Configuration Example { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - Enabled = $False # Updated Property + AcceptSecurityIdentifierInformation = $False # Updated Property + Enabled = $True Ensure = "Present" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOPerimeterConfiguration.md b/docs/docs/resources/exchange/EXOPerimeterConfiguration.md index 921f997dde..3b82181618 100644 --- a/docs/docs/resources/exchange/EXOPerimeterConfiguration.md +++ b/docs/docs/resources/exchange/EXOPerimeterConfiguration.md @@ -56,7 +56,7 @@ Configuration Example EXOPerimeterConfiguration 'ConfigurePerimeterConfiguration' { IsSingleInstance = 'Yes' - GatewayIPAddresses = '123.0.0.1' + #GatewayIPAddresses = '123.0.0.1' Ensure = 'Present' Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXOQuarantinePolicy.md b/docs/docs/resources/exchange/EXOQuarantinePolicy.md index 86ee5e75f5..c4b147b75a 100644 --- a/docs/docs/resources/exchange/EXOQuarantinePolicy.md +++ b/docs/docs/resources/exchange/EXOQuarantinePolicy.md @@ -69,7 +69,7 @@ Configuration Example { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $False; - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } @@ -100,7 +100,7 @@ Configuration Example { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $True; # Updated Property - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } @@ -129,7 +129,7 @@ Configuration Example { EXOQuarantinePolicy 'ConfigureQuarantinePolicy' { - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Absent" Credential = $Credscredential } diff --git a/docs/docs/resources/exchange/EXORemoteDomain.md b/docs/docs/resources/exchange/EXORemoteDomain.md index 3237473427..c3d5db54c0 100644 --- a/docs/docs/resources/exchange/EXORemoteDomain.md +++ b/docs/docs/resources/exchange/EXORemoteDomain.md @@ -132,9 +132,9 @@ Configuration Example DisplaySenderName = $True DomainName = "contoso.com" IsInternal = $False - LineWrapSize = "Integration" + LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False diff --git a/docs/docs/resources/exchange/EXORoleAssignmentPolicy.md b/docs/docs/resources/exchange/EXORoleAssignmentPolicy.md index 1b483a8b3b..fdfcda774f 100644 --- a/docs/docs/resources/exchange/EXORoleAssignmentPolicy.md +++ b/docs/docs/resources/exchange/EXORoleAssignmentPolicy.md @@ -87,8 +87,8 @@ Configuration Example EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" - Description = "This policy grants end users the permission to set their options in Outlook on the web and perform other self-administration tasks." - IsDefault = $False # Updated Property + Description = "Updated Description" # Updated Property + IsDefault = $True Roles = @("My Marketplace Apps","MyVoiceMail","MyDistributionGroups","MyRetentionPolicies","MyContactInformation","MyBaseOptions","MyTextMessaging","MyDistributionGroupMembership","MyProfileInformation","My Custom Apps","My ReadWriteMailbox Apps") Ensure = "Present" Credential = $Credscredential From 8173d026c06a7e96666228fd4c5761d6aaa6e191 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Sat, 10 Feb 2024 14:41:29 +0000 Subject: [PATCH 123/171] Updated {Create} EXO Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 index 4dd7a69343..7f5f58570e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Create.Tests.ps1 @@ -468,7 +468,7 @@ EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $true Ensure = "Present" @@ -619,6 +619,7 @@ { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" + AcceptSecurityIdentifierInformation = $true Enabled = $True Ensure = "Present" Credential = $Credscredential @@ -650,7 +651,7 @@ { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $False; - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } From d3d81cc8761aca75bb0fd0f4ab0084c0d6123b67 Mon Sep 17 00:00:00 2001 From: Vasily Date: Mon, 12 Feb 2024 13:44:16 +0100 Subject: [PATCH 124/171] Update MSFT_AADGroup.psm1 fixed and removed an extra bracket in line #1103 if ($matchConditionFound -or $Filter -like "*endsWith*") --- .../DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 index e8b08e2411..c000517482 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADGroup/MSFT_AADGroup.psm1 @@ -1100,7 +1100,7 @@ function Export-TargetResource } # If any attribute matches, add parameters to $ExportParameters - if ($matchConditionFound -or $Filter -like "*endsWith*")) { + if ($matchConditionFound -or $Filter -like "*endsWith*") { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } From c2e85e9fb6b44131c257a0b8475aeeee270244c3 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 12 Feb 2024 16:32:07 -0500 Subject: [PATCH 125/171] Updated MSCloudLoginAssistant --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f0e77a756..32b95f5ffb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ to the update logic flow. * DEPENDENCIES * Updated Microsoft.Graph dependencies to version 2.13.1. + * Updated MSCloudLoginAssistant to version 1.1.12. # 1.24.207.2 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 5c97f552db..225218fe2f 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -86,7 +86,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.11" + RequiredVersion = "1.1.12" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index d83b9d82c6..40a70a65d9 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -897,7 +897,8 @@ function Test-M365DSCParameterState { $EventMessage = [System.Text.StringBuilder]::New() $EventMessage.Append("`r`n") | Out-Null - $EventMessage.Append(" `r`n") | Out-Null + $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues + $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null foreach ($key in $DriftedParameters.Keys) @@ -917,7 +918,6 @@ function Test-M365DSCParameterState $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) } - $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues $driftedData.Add('Tenant', $TenantName) $driftedData.Add('Resource', $source.Split('_')[1]) Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData @@ -3771,11 +3771,11 @@ function Get-M365DSCAuthenticationMode { $AuthenticationType = 'ServicePrincipalWithPath' } - elseif ($Parameters.Credentials -and $Parameters.ApplicationId) + elseif ($Parameters.Credential -and $Parameters.ApplicationId) { $AuthenticationType = 'CredentialsWithApplicationId' } - elseif ($Parameters.Credentials) + elseif ($Parameters.Credential) { $AuthenticationType = 'Credentials' } From 1b9fc96726e45c0f14642e129eb9195d6cb41e63 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 13 Feb 2024 09:23:53 -0500 Subject: [PATCH 126/171] Updated MSCloudLoginAssistant --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 | 2 +- .../Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 | 7 +++++-- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 8 ++++---- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32b95f5ffb..8a5b0afdef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ to the update logic flow. * DEPENDENCIES * Updated Microsoft.Graph dependencies to version 2.13.1. - * Updated MSCloudLoginAssistant to version 1.1.12. + * Updated MSCloudLoginAssistant to version 1.1.13. # 1.24.207.2 diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 225218fe2f..39b260bc2f 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -86,7 +86,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.12" + RequiredVersion = "1.1.13" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 index de0b2dc117..6514eb30e3 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 @@ -80,7 +80,7 @@ function New-M365DSCLogEntry #region Telemetry $driftedData = [System.Collections.Generic.Dictionary[[String], [String]]]::new() - $driftedData.Add('Event', 'Error') + $driftedData.Add('M365DSCOperation', 'Error') $driftedData.Add('CustomMessage', $Message) $driftedData.Add('Source', $Source) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index f42225a049..23c203d16a 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -216,7 +216,9 @@ function Add-M365DSCTelemetryEvent { $Data.Add('M365DSCOperation', 'Export') } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.') + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') { $Data.Add('M365DSCOperation', 'MonitoringScheduled') } @@ -224,7 +226,8 @@ function Add-M365DSCTelemetryEvent { $Data.Add('M365DSCOperation', 'MonitoringManual') } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.') + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') { $Data.Add('M365DSCOperation', 'ApplyingConfiguration') } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 40a70a65d9..2b3ab15ca4 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1256,7 +1256,7 @@ function Export-M365DSCConfiguration #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() - $data.Add('Event', 'Extraction') + $data.Add('M365DSCOperation', 'Extraction') $data.Add('Path', [System.String]::IsNullOrEmpty($Path)) $data.Add('FileName', $null -ne [System.String]::IsNullOrEmpty($FileName)) @@ -1718,7 +1718,7 @@ function New-M365DSCConnection { $message = 'Both Authentication methods are attempted' Write-Verbose -Message $message - $data.Add('Event', 'Error') + $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = "You can't specify both the Credential and CertificateThumbprint" $data.Add('CustomMessage', $errorText) @@ -1735,7 +1735,7 @@ function New-M365DSCConnection $message = 'No Authentication method was provided' Write-Verbose -Message $message $message += "`r`nProvided Keys --> $($InboundParameters.Keys)" - $data.Add('Event', 'Error') + $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = 'You must specify either the Credential or ApplicationId, TenantId and CertificateThumbprint parameters.' $data.Add('CustomMessage', $errorText) @@ -1875,7 +1875,7 @@ function New-M365DSCConnection $message = 'No Authentication method was provided' Write-Verbose -Message $message $message += "`r`nProvided Keys --> $($InboundParameters.Keys)" - $data.Add('Event', 'Error') + $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = 'You must specify either the Credential or ApplicationId, TenantId and CertificateThumbprint parameters.' $data.Add('CustomMessage', $errorText) From cf116c5ca356495504656b29f5d390d3bdfd1f30 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 08:30:31 -0500 Subject: [PATCH 127/171] Updated DSCParser --- CHANGELOG.md | 1 + Modules/Microsoft365DSC/Dependencies/Manifest.psd1 | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a5b0afdef..f005547c25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Fixes an issue where an empty MinPasswordLength value was always passed down to the update logic flow. * DEPENDENCIES + * Updated DSCParser to version 1.4.0.2. * Updated Microsoft.Graph dependencies to version 2.13.1. * Updated MSCloudLoginAssistant to version 1.1.13. diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 39b260bc2f..437b3cc54f 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -2,7 +2,7 @@ Dependencies = @( @{ ModuleName = 'DSCParser' - RequiredVersion = '1.4.0.1' + RequiredVersion = '1.4.0.2' }, @{ ModuleName = 'ExchangeOnlineManagement' From 4f6637e1952efb51ecc17f95d0d54db3a745795b Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 14 Feb 2024 15:01:48 +0000 Subject: [PATCH 128/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/intune/IntuneAppConfigurationPolicy.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/docs/resources/intune/IntuneAppConfigurationPolicy.md b/docs/docs/resources/intune/IntuneAppConfigurationPolicy.md index 4e60a0ee8f..cecb30f398 100644 --- a/docs/docs/resources/intune/IntuneAppConfigurationPolicy.md +++ b/docs/docs/resources/intune/IntuneAppConfigurationPolicy.md @@ -4,6 +4,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | +| **Id** | Write | String | Key of the entity. Read-Only. | | | **DisplayName** | Key | String | Display name of the app configuration policy. | | | **Description** | Write | String | Description of the app configuration policy. | | | **Assignments** | Write | MSFT_DeviceManagementConfigurationPolicyAssignments[] | Assignments of the Intune Policy. | | From 1a7bff4d10096d9404ab9d174b9e50c216b11691 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 10:05:46 -0500 Subject: [PATCH 129/171] Various changes to ensure keys aren't already present --- .../Modules/M365DSCTelemetryEngine.psm1 | 19 +++-- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 80 ++++++++++++++----- 2 files changed, 73 insertions(+), 26 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 23c203d16a..6dfd9325b1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -70,19 +70,22 @@ function Add-M365DSCTelemetryEvent $Data.Add('ProjectName', $ProjectName) } - if (-not [System.String]::IsNullOrEmpty($Data.Principal)) + if (-not $Data.ContainsKey('Tenant')) { - if ($Data.Principal -like '*@*.*') + if (-not [System.String]::IsNullOrEmpty($Data.Principal)) { - $principalValue = $Data.Principal.Split('@')[1] + if ($Data.Principal -like '*@*.*') + { + $principalValue = $Data.Principal.Split('@')[1] + $Data.Add('Tenant', $principalValue) + } + } + elseif (-not [System.String]::IsNullOrEmpty($Data.TenantId)) + { + $principalValue = $Data.TenantId $Data.Add('Tenant', $principalValue) } } - elseif (-not [System.String]::IsNullOrEmpty($Data.TenantId)) - { - $principalValue = $Data.TenantId - $Data.Add('Tenant', $principalValue) - } $Data.Remove('TenandId') | Out-Null $Data.Remove('Principal') | Out-Null diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 2b3ab15ca4..846efd40bd 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -918,7 +918,10 @@ function Test-M365DSCParameterState $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) } - $driftedData.Add('Tenant', $TenantName) + if (-not $Data.ContainsKey('Tenant')) + { + $driftedData.Add('Tenant', $TenantName) + } $driftedData.Add('Resource', $source.Split('_')[1]) Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData #endregion @@ -928,7 +931,11 @@ function Test-M365DSCParameterState #region Telemetry $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues $data.Add('Event', 'ConfigurationDrift') - $data.Add('Tenant', $TenantName) + + if (-not $Data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $TenantName) + } #endregion $EventMessage.Append(" `r`n") | Out-Null @@ -1281,13 +1288,13 @@ function Export-M365DSCConfiguration Write-Verbose -Message 'No existing connections to Microsoft Graph' } - if (-not [System.String]::IsNullOrEmpty($TenantId)) + if (-not [System.String]::IsNullOrEmpty($TenantId) -and -not $data.ContainsKey('Tenant')) { $data.Add('Tenant', $TenantId) } else { - if ($Credential) + if ($Credential -and -not $data.ContainsKey('Tenant')) { $tenant = $Credential.UserName.Split('@')[1] $data.Add('Tenant', $tenant) @@ -1758,8 +1765,11 @@ function New-M365DSCConnection try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } } catch { @@ -1780,8 +1790,11 @@ function New-M365DSCConnection try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } } catch { @@ -1808,8 +1821,11 @@ function New-M365DSCConnection try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } } catch { @@ -1830,8 +1846,11 @@ function New-M365DSCConnection try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } } catch { @@ -1860,7 +1879,10 @@ function New-M365DSCConnection -SkipModuleReload $Global:CurrentModeIsExport $data.Add('ConnectionType', 'ServicePrincipalWithPath') - $data.Add('Tenant', $InboundParameters.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithPath' } @@ -1885,7 +1907,17 @@ function New-M365DSCConnection else { $data.Add('ConnectionType', 'ServicePrincipalWithPath') - $data.Add('Tenant', $InboundParameters.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + if (-not [System.String]::IsNullOrEmpty($InboundParameters.TenantId)) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + elseif ($ null -ne $InboundParameters.Credential) + { + $data.Add('Tenant', $InboundParameters.Credential.Split('@')[1]) + } + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithPath' @@ -1908,7 +1940,10 @@ function New-M365DSCConnection $data.Add('ConnectionType', 'ServicePrincipalWithSecret') - $data.Add('Tenant', $InboundParameters.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithSecret' } @@ -1923,7 +1958,10 @@ function New-M365DSCConnection $data.Add('ConnectionType', 'ServicePrincipalWithSecret') - $data.Add('Tenant', $InboundParameters.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithSecret' } @@ -1939,7 +1977,10 @@ function New-M365DSCConnection -Url $Url $data.Add('ConnectionType', 'ServicePrincipalWithThumbprint') - $data.Add('Tenant', $InboundParameters.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithThumbprint' } @@ -1966,7 +2007,10 @@ function New-M365DSCConnection $data.Add('ConnectionType', 'ManagedIdentity') - $data.Add('Tenant', $Global:MSCloudLoginConnectionProfile.MicrosoftGraph.TenantId) + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ManagedIdentity' } From 6db47741d8571095ccd82736148e104174fb3d46 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 14 Feb 2024 16:06:15 +0000 Subject: [PATCH 130/171] Updated Resources and Cmdlet documentation pages --- .../SCDLPComplianceRule.md | 71 ++++++++++--------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md index 0d09c8ef2e..6e2890ec62 100644 --- a/docs/docs/resources/security-compliance/SCDLPComplianceRule.md +++ b/docs/docs/resources/security-compliance/SCDLPComplianceRule.md @@ -8,7 +8,7 @@ | **Policy** | Required | String | Name of the associated DLP Compliance Policy. | | | **AccessScope** | Write | String | The AccessScope parameter specifies a condition for the DLP rule that's based on the access scope of the content. The rule is applied to content that matches the specified access scope. | `InOrganization`, `NotInOrganization`, `None` | | **BlockAccess** | Write | Boolean | The BlockAccess parameter specifies an action for the DLP rule that blocks access to the source item when the conditions of the rule are met. $true: Blocks further access to the source item that matched the rule. The owner, author, and site owner can still access the item. $false: Allows access to the source item that matched the rule. This is the default value. | | -| **BlockAccessScope** | Write | String | The BlockAccessScope parameter specifies the scope of the block access action. | `All`, `PerUser` | +| **BlockAccessScope** | Write | String | The BlockAccessScope parameter specifies the scope of the block access action. | `All`, `PerUser`, `None` | | **Comment** | Write | String | The Comment parameter specifies an optional comment. If you specify a value that contains spaces, enclose the value in quotation marks. | | | **ContentContainsSensitiveInformation** | Write | MSFT_SCDLPContainsSensitiveInformation | The ContentContainsSensitiveInformation parameter specifies a condition for the rule that's based on a sensitive information type match in content. The rule is applied to content that contains the specified sensitive information type. | | | **ExceptIfContentContainsSensitiveInformation** | Write | MSFT_SCDLPContainsSensitiveInformation | The ExceptIfContentContainsSensitiveInformation parameter specifies an exception for the rule that's based on a sensitive information type match in content. The rule isn't applied to content that contains the specified sensitive information type. | | @@ -42,42 +42,43 @@ | **ExceptIfProcessingLimitExceeded** | Write | Boolean | The ExceptIfProcessingLimitExceeded parameter specifies an exception for the DLP rule that looks for files where scanning couldn't complete. | | | **DocumentIsPasswordProtected** | Write | Boolean | The DocumentIsPasswordProtected parameter specifies a condition for the DLP rule that looks for password protected files (because the contents of the file can't be inspected). Password detection only works for Office documents and .zip files. | | | **ExceptIfDocumentIsPasswordProtected** | Write | Boolean | The ExceptIfDocumentIsPasswordProtected parameter specifies an exception for the DLP rule that looks for password protected files (because the contents of the file can't be inspected). Password detection only works for Office documents and .zip files. | | +| **MessageTypeMatches** | Write | StringArray[] | The MessageTypeMatches parameter specifies a condition for the DLP rule that looks for types of SMIME message patterns. | | +| **FromScope** | Write | StringArray[] | The FromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule. | | +| **ExceptIfFromScope** | Write | StringArray[] | The ExceptIfFromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule. | | +| **SubjectContainsWords** | Write | StringArray[] | The SubjectContainsWords parameter specifies a condition for the DLP rule that looks for words or phrases in the Subject field of messages. You can specify multiple words or phrases separated by commas. | | +| **SubjectMatchesPatterns** | Write | StringArray[] | The SubjectMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions. | | +| **SubjectOrBodyContainsWords** | Write | StringArray[] | The SubjectOrBodyContainsWords parameter specifies a condition for the rule that looks for words in the Subject field or body of messages. | | +| **SubjectOrBodyMatchesPatterns** | Write | StringArray[] | The SubjectOrBodyMatchesPatterns parameter specifies a condition for the rule that looks for text patterns in the Subject field or body of messages. | | +| **ContentCharacterSetContainsWords** | Write | StringArray[] | The ContentCharacterSetContainsWords parameter specifies a condition for the rule that looks for character set names in messages. You can specify multiple values separated by commas. | | +| **DocumentNameMatchesPatterns** | Write | StringArray[] | The DocumentNameMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions. | | +| **DocumentNameMatchesWords** | Write | StringArray[] | The DocumentNameMatchesWords parameter specifies a condition for the DLP rule that looks for words or phrases in the name of message attachments. | | +| **ExceptIfAnyOfRecipientAddressContainsWords** | Write | StringArray[] | he ExceptIfAnyOfRecipientAddressContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in recipient email addresses. | | +| **ExceptIfAnyOfRecipientAddressMatchesPatterns** | Write | StringArray[] | The ExceptIfAnyOfRecipientAddressMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in recipient email addresses by using regular expressions. | | +| **ExceptIfContentCharacterSetContainsWords** | Write | StringArray[] | The ExceptIfContentCharacterSetContainsWords parameter specifies an exception for the rule that looks for character set names in messages. | | +| **ExceptIfContentPropertyContainsWords** | Write | StringArray[] | The ExceptIfContentPropertyContainsWords parameter specifies an exception for the DLP rule that's based on a property match in content. | | +| **ExceptIfDocumentNameMatchesPatterns** | Write | StringArray[] | The ExceptIfDocumentNameMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions. | | +| **ExceptIfDocumentNameMatchesWords** | Write | StringArray[] | The ExceptIfDocumentNameMatchesWords parameter specifies an exception for the DLP rule that looks for words or phrases in the name of message attachments. | | +| **ExceptIfFromAddressContainsWords** | Write | StringArray[] | The ExceptIfFromAddressContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in the sender's email address. | | +| **ExceptIfFromAddressMatchesPatterns** | Write | StringArray[] | The ExceptIfFromAddressMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the sender's email address by using regular expressions. | | +| **FromAddressContainsWords** | Write | StringArray[] | The FromAddressContainsWords parameter specifies a condition for the DLP rule that looks for words or phrases in the sender's email address. | | +| **FromAddressMatchesPatterns** | Write | StringArray[] | The FromAddressMatchesPatterns parameter specifies a condition for the DLP rule that looks for text patterns in the sender's email address by using regular expressions. | | +| **ExceptIfMessageTypeMatches** | Write | StringArray[] | The ExceptIfMessageTypeMatches parameter specifies an exception for the rule that looks for messages of the specified type. | | +| **RecipientDomainIs** | Write | StringArray[] | The RecipientDomainIs parameter specifies a condition for the DLP rule that looks for recipients with email addresses in the specified domains. | | +| **ExceptIfRecipientDomainIs** | Write | StringArray[] | The ExceptIfRecipientDomainIs parameter specifies an exception for the DLP rule that looks for recipients with email addresses in the specified domains. | | +| **ExceptIfSenderDomainIs** | Write | StringArray[] | The ExceptIfSenderDomainIs parameter specifies an exception for the DLP rule that looks for messages from senders with email address in the specified domains. | | +| **ExceptIfSenderIPRanges** | Write | StringArray[] | The ExceptIfSenderIpRanges parameter specifies an exception for the DLP rule that looks for senders whose IP addresses matches the specified value, or fall within the specified ranges. | | +| **ExceptIfSentTo** | Write | StringArray[] | The ExceptIfSentTo parameter specifies an exception for the DLP rule that looks for recipients in messages. You identify the recipients by email address. | | +| **ExceptIfSubjectContainsWords** | Write | StringArray[] | The ExceptIfSubjectContainsWords parameter specifies an exception for the DLP rule that looks for words or phrases in the Subject field of messages. | | +| **ExceptIfSubjectMatchesPatterns** | Write | StringArray[] | The ExceptIfSubjectMatchesPatterns parameter specifies an exception for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions. | | +| **ExceptIfSubjectOrBodyContainsWords** | Write | StringArray[] | The ExceptIfSubjectOrBodyContainsWords parameter specifies an exception for the rule that looks for words in the Subject field or body of messages. | | +| **ExceptIfSubjectOrBodyMatchesPatterns** | Write | StringArray[] | The ExceptIfSubjectOrBodyMatchesPatterns parameter specifies an exception for the rule that looks for text patterns in the Subject field or body of messages. | | +| **DocumentContainsWords** | Write | StringArray[] | The DocumentContainsWords parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked. | | +| **SentToMemberOf** | Write | StringArray[] | The SentToMemberOf parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups. | | +| **ContentIsNotLabeled** | Write | Boolean | The ContentIsNotLabeled parameter specifies if the content is labeled. A True or False condition. | | +| **SetHeader** | Write | StringArray[] | The SetHeader The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas | | | **ContentExtensionMatchesWords** | Write | StringArray[] | The ContentExtensionMatchesWords parameter specifies a condition for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas. | | | **ExceptIfContentExtensionMatchesWords** | Write | StringArray[] | The ExceptIfContentExtensionMatchesWords parameter specifies an exception for the DLP rule that looks for words in file name extensions. You can specify multiple words separated by commas. | | -| **MessageTypeMatches** | Write | StringArray[] | The MessageTypeMatches parameter specifies a condition for the DLP rule that looks for types of SMIME message patterns.| | -| **FromScope** | Write | StringArray[] | The FromScope parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.| | -| **ExceptIfFromScope** | Write | StringArray[] | The parameter specifies wether messages from inside or outside the organisation are in scope for the DLP rule.| | -| **SubjectContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the Subject field of messages. You can specify multiple words or phrases separated by commas.| | -| **SubjectMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.| | -| **SubjectOrBodyContainsWords** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for words in the Subject field or body of messages.| | -| **SubjectOrBodyMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for text patterns in the Subject field or body of messages.| | -| **ContentCharacterSetContainsWords** | Write | StringArray[] | The parameter specifies a condition for the rule that looks for character set names in messages. You can specify multiple values separated by commas.| | -| **DocumentNameMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.| | -| **DocumentNameMatchesWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the name of message attachments. | | -**ExceptIfAnyOfRecipientAddressContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in recipient email addresses.| | -| **ExceptIfAnyOfRecipientAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in recipient email addresses by using regular expressions.| | -| **ExceptIfContentCharacterSetContainsWords** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for character set names in messages.| | -| **ExceptIfContentPropertyContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that's based on a property match in content.| | -| **ExceptIfDocumentNameMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the name of message attachments by using regular expressions.| | -| **ExceptIfDocumentNameMatchesWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the name of message attachments.| | -| **ExceptIfFromAddressContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the sender's email address.| | -| **ExceptIfFromAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the sender's email address by using regular expressions.| | -| **FromAddressContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words or phrases in the sender's email address.| | -| **FromAddressMatchesPatterns** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for text patterns in the sender's email address by using regular expressions. | | -| **ExceptIfMessageTypeMatches** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for messages of the specified type.| | -| **RecipientDomainIs** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for recipients with email addresses in the specified domains.| | -| **ExceptIfRecipientDomainIs** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for recipients with email addresses in the specified domains.| | -| **ExceptIfSenderDomainIs** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for messages from senders with email address in the specified domains. | | -| **ExceptIfSenderIpRanges** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for senders whose IP addresses matches the specified value, or fall within the specified ranges.| | -| **ExceptIfSentTo** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for recipients in messages. You identify the recipients by email address.| | -| **ExceptIfSubjectContainsWords** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for words or phrases in the Subject field of messages.| | -| **ExceptIfSubjectMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the DLP rule that looks for text patterns in the Subject field of messages by using regular expressions.| | -| **ExceptIfSubjectOrBodyContainsWords** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for words in the Subject field or body of messages.| | -| **ExceptIfSubjectOrBodyMatchesPatterns** | Write | StringArray[] | The parameter specifies an exception for the rule that looks for text patterns in the Subject field or body of messages.| | -| **DocumentContainsWords** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for words in message attachments. Only supported attachment types are checked.| | -| **SentToMemberOf** | Write | StringArray[] | The parameter specifies a condition for the DLP rule that looks for messages sent to members of distribution groups, dynamic distribution groups, or mail-enabled security groups.| | -| **ContentIsNotLabeled** | Write | Boolean | The parameter specifies if the content is labeled. A True or False condition. | | -| **SetHeader** | Write | StringArray[] | The SetHeader parameter specifies an action for the DLP rule that adds or modifies a header field and value in the message header. You can specify multiple header name and value pairs separated by commas| | + ### MSFT_SCDLPSensitiveInformation #### Parameters From a3b9db8da0371117214452585f46dc88d30ee355 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 14 Feb 2024 17:16:59 +0100 Subject: [PATCH 131/171] Updated unit tests to check for description field in schema --- Tests/QA/Microsoft365DSC.Resources.Tests.ps1 | 207 ++++++++++++------- 1 file changed, 138 insertions(+), 69 deletions(-) diff --git a/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 b/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 index 529e7530e5..73e9870f07 100644 --- a/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 +++ b/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 @@ -8,12 +8,107 @@ } } -Describe -Name "Check schema for resource ''" -ForEach $schemaFiles{ - BeforeAll { - function Get-MofSchemaObject +BeforeAll { + function Get-MofSchemaObject + { + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $FileName + ) + + $temporaryPath = (Get-Item -Path env:TEMP).Value + + #region Workaround for OMI_BaseResource inheritance not resolving. + + $filePath = (Resolve-Path -Path $FileName).Path + $tempFilePath = Join-Path -Path $temporaryPath -ChildPath "DscMofHelper_$((New-Guid).Guid).tmp" + $rawContent = (Get-Content -Path $filePath -Raw) -replace '\s*:\s*OMI_BaseResource' + + Set-Content -LiteralPath $tempFilePath -Value $rawContent -ErrorAction 'Stop' + + # .NET methods don't like PowerShell drives + $tempFilePath = Convert-Path -Path $tempFilePath + + #endregion + + try + { + $exceptionCollection = [System.Collections.ObjectModel.Collection[System.Exception]]::new() + $moduleInfo = [System.Tuple]::Create('Module', [System.Version] '1.0.0') + + $class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses( + $tempFilePath, $moduleInfo, $exceptionCollection + ) + + if ($null -eq $class) + { + throw "No classes found in the schema file" + } + } + catch + { + throw "Failed to import classes from file $FileName. Error $_" + } + finally + { + Remove-Item -LiteralPath $tempFilePath -Force + } + + foreach ($currentCimClass in $class) + { + $attributes = foreach ($property in $currentCimClass.CimClassProperties) + { + $state = switch ($property.flags) + { + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key } + { + 'Key' + } + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required } + { + 'Required' + } + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly } + { + 'Read' + } + default + { + 'Write' + } + } + + @{ + Name = $property.Name + State = $state + DataType = $property.CimType + ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value + IsArray = $property.CimType -gt 16 + Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value + EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value + } + } + + @{ + ClassName = $currentCimClass.CimClassName + Attributes = $attributes + ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value + FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value + } + } + } +} + +Describe -Name "Check schema for resource ''" -ForEach $schemaFiles { + BeforeDiscovery { + function Confirm-MofSchema { [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] + [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] @@ -44,95 +139,69 @@ Describe -Name "Check schema for resource ''" -ForEach $schemaFile $class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses( $tempFilePath, $moduleInfo, $exceptionCollection ) + + if ($null -eq $class) + { + return $false + } + else + { + return $true + } } catch { - throw "Failed to import classes from file $FileName. Error $_" + return $false } finally { Remove-Item -LiteralPath $tempFilePath -Force } - - foreach ($currentCimClass in $class) - { - $attributes = foreach ($property in $currentCimClass.CimClassProperties) - { - $state = switch ($property.flags) - { - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key } - { - 'Key' - } - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required } - { - 'Required' - } - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly } - { - 'Read' - } - default - { - 'Write' - } - } - - @{ - Name = $property.Name - State = $state - DataType = $property.CimType - ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value - IsArray = $property.CimType -gt 16 - Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value - EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value - } - } - - @{ - ClassName = $currentCimClass.CimClassName - Attributes = $attributes - ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value - FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value - } - } } - } - It 'Schema should be read successfully' { - { Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw + $skipTest = -not (Confirm-MofSchema -FileName $FullName) } - It 'Schema should have a Key parameter' { - $mofSchemas = Get-MofSchemaObject -FileName $FullName - $attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes - $keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count - $keyCount | Should -BeGreaterThan 1 + Context 'Validate if the schema is correct' { + It 'Schema should be read successfully' { + { $mofSchemas = Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw + } } - It 'Schema should contain an instance of all used subclasses' { - $mofSchemas = Get-MofSchemaObject -FileName $FullName + Context 'Run all schema checks' -Skip:$skipTest { + BeforeAll { + $mofSchemas = Get-MofSchemaObject -FileName $FullName + } - $errors = 0 + It 'Schema should have a Key parameter' { + $attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes + $keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count + $keyCount | Should -BeGreaterThan 1 + } - $availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName } + It 'Schema should contain an instance of all used subclasses' { + $availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName } - foreach ($mofSchema in $mofSchemas) - { - foreach ($attribute in $mofSchema.Attributes) + foreach ($mofSchema in $mofSchemas) { - if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne "MSFT_Credential") + foreach ($attribute in $mofSchema.Attributes) { - if ($attribute.EmbeddedInstance -notin $availableClasses) + if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne 'MSFT_Credential') { - Write-Host "[ERROR] Property $($attribute.Name) in class $($mofSchema.ClassName) / Specified EmbeddedInstance: $($attribute.EmbeddedInstance) not found!" -ForegroundColor Red - $errors++ + $attribute.EmbeddedInstance | Should -BeIn $availableClasses } } } } - $errors | Should -Be 0 + It 'Schema should have a description for all properties' { + foreach ($mofSchema in $mofSchemas) + { + foreach ($attribute in $mofSchema.Attributes) + { + $attribute.Description | Should -Not -BeNullOrEmpty + } + } + } } - } From 0c6c571f1094fb4ace1c00f813b4a218895e7754 Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 14 Feb 2024 17:16:59 +0100 Subject: [PATCH 132/171] Updated unit tests to check for description field in schema --- Tests/QA/Microsoft365DSC.Resources.Tests.ps1 | 207 ++++++++++++------- 1 file changed, 138 insertions(+), 69 deletions(-) diff --git a/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 b/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 index 529e7530e5..73e9870f07 100644 --- a/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 +++ b/Tests/QA/Microsoft365DSC.Resources.Tests.ps1 @@ -8,12 +8,107 @@ } } -Describe -Name "Check schema for resource ''" -ForEach $schemaFiles{ - BeforeAll { - function Get-MofSchemaObject +BeforeAll { + function Get-MofSchemaObject + { + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $FileName + ) + + $temporaryPath = (Get-Item -Path env:TEMP).Value + + #region Workaround for OMI_BaseResource inheritance not resolving. + + $filePath = (Resolve-Path -Path $FileName).Path + $tempFilePath = Join-Path -Path $temporaryPath -ChildPath "DscMofHelper_$((New-Guid).Guid).tmp" + $rawContent = (Get-Content -Path $filePath -Raw) -replace '\s*:\s*OMI_BaseResource' + + Set-Content -LiteralPath $tempFilePath -Value $rawContent -ErrorAction 'Stop' + + # .NET methods don't like PowerShell drives + $tempFilePath = Convert-Path -Path $tempFilePath + + #endregion + + try + { + $exceptionCollection = [System.Collections.ObjectModel.Collection[System.Exception]]::new() + $moduleInfo = [System.Tuple]::Create('Module', [System.Version] '1.0.0') + + $class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses( + $tempFilePath, $moduleInfo, $exceptionCollection + ) + + if ($null -eq $class) + { + throw "No classes found in the schema file" + } + } + catch + { + throw "Failed to import classes from file $FileName. Error $_" + } + finally + { + Remove-Item -LiteralPath $tempFilePath -Force + } + + foreach ($currentCimClass in $class) + { + $attributes = foreach ($property in $currentCimClass.CimClassProperties) + { + $state = switch ($property.flags) + { + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key } + { + 'Key' + } + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required } + { + 'Required' + } + { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly } + { + 'Read' + } + default + { + 'Write' + } + } + + @{ + Name = $property.Name + State = $state + DataType = $property.CimType + ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value + IsArray = $property.CimType -gt 16 + Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value + EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value + } + } + + @{ + ClassName = $currentCimClass.CimClassName + Attributes = $attributes + ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value + FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value + } + } + } +} + +Describe -Name "Check schema for resource ''" -ForEach $schemaFiles { + BeforeDiscovery { + function Confirm-MofSchema { [CmdletBinding()] - [OutputType([System.Collections.Hashtable])] + [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] @@ -44,95 +139,69 @@ Describe -Name "Check schema for resource ''" -ForEach $schemaFile $class = [Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache]::ImportClasses( $tempFilePath, $moduleInfo, $exceptionCollection ) + + if ($null -eq $class) + { + return $false + } + else + { + return $true + } } catch { - throw "Failed to import classes from file $FileName. Error $_" + return $false } finally { Remove-Item -LiteralPath $tempFilePath -Force } - - foreach ($currentCimClass in $class) - { - $attributes = foreach ($property in $currentCimClass.CimClassProperties) - { - $state = switch ($property.flags) - { - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Key } - { - 'Key' - } - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::Required } - { - 'Required' - } - { $_ -band [Microsoft.Management.Infrastructure.CimFlags]::ReadOnly } - { - 'Read' - } - default - { - 'Write' - } - } - - @{ - Name = $property.Name - State = $state - DataType = $property.CimType - ValueMap = $property.Qualifiers.Where( { $_.Name -eq 'ValueMap' }).Value - IsArray = $property.CimType -gt 16 - Description = $property.Qualifiers.Where( { $_.Name -eq 'Description' }).Value - EmbeddedInstance = $property.Qualifiers.Where( { $_.Name -eq 'EmbeddedInstance' }).Value - } - } - - @{ - ClassName = $currentCimClass.CimClassName - Attributes = $attributes - ClassVersion = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'ClassVersion' }).Value - FriendlyName = $currentCimClass.CimClassQualifiers.Where( { $_.Name -eq 'FriendlyName' }).Value - } - } } - } - It 'Schema should be read successfully' { - { Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw + $skipTest = -not (Confirm-MofSchema -FileName $FullName) } - It 'Schema should have a Key parameter' { - $mofSchemas = Get-MofSchemaObject -FileName $FullName - $attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes - $keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count - $keyCount | Should -BeGreaterThan 1 + Context 'Validate if the schema is correct' { + It 'Schema should be read successfully' { + { $mofSchemas = Get-MofSchemaObject -FileName $FullName } | Should -Not -Throw + } } - It 'Schema should contain an instance of all used subclasses' { - $mofSchemas = Get-MofSchemaObject -FileName $FullName + Context 'Run all schema checks' -Skip:$skipTest { + BeforeAll { + $mofSchemas = Get-MofSchemaObject -FileName $FullName + } - $errors = 0 + It 'Schema should have a Key parameter' { + $attributes = ($mofSchemas | Where-Object { [String]::IsNullOrEmpty($_.FriendlyName) -eq $false }).Attributes + $keyCount = ($attributes | Where-Object { $_.State -eq 'Key' }).Count + $keyCount | Should -BeGreaterThan 1 + } - $availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName } + It 'Schema should contain an instance of all used subclasses' { + $availableClasses = $mofSchemas.ClassName | Where-Object -FilterScript { $_ -ne $ResourceName } - foreach ($mofSchema in $mofSchemas) - { - foreach ($attribute in $mofSchema.Attributes) + foreach ($mofSchema in $mofSchemas) { - if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne "MSFT_Credential") + foreach ($attribute in $mofSchema.Attributes) { - if ($attribute.EmbeddedInstance -notin $availableClasses) + if ([String]::IsNullOrEmpty($attribute.EmbeddedInstance) -eq $false -and $attribute.EmbeddedInstance -ne 'MSFT_Credential') { - Write-Host "[ERROR] Property $($attribute.Name) in class $($mofSchema.ClassName) / Specified EmbeddedInstance: $($attribute.EmbeddedInstance) not found!" -ForegroundColor Red - $errors++ + $attribute.EmbeddedInstance | Should -BeIn $availableClasses } } } } - $errors | Should -Be 0 + It 'Schema should have a description for all properties' { + foreach ($mofSchema in $mofSchemas) + { + foreach ($attribute in $mofSchema.Attributes) + { + $attribute.Description | Should -Not -BeNullOrEmpty + } + } + } } - } From 1f39e26ac21c68e82b677af2e0c204c8f21a33ba Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 14 Feb 2024 17:19:02 +0100 Subject: [PATCH 133/171] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b04ca09a5d..1c1febe3c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ * Fix nested change detection for CIMInstances * Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report FIXES [#4291](https://github.com/microsoft/Microsoft365DSC/issues/4291) + * Added new QA test to check for missing description in resource schema # 1.24.207.2 From 32fa1cce2e7202e594d1a03bec8433c1bf9880cf Mon Sep 17 00:00:00 2001 From: Yorick Kuijs Date: Wed, 14 Feb 2024 17:24:29 +0100 Subject: [PATCH 134/171] Removed incorrect empty string --- CHANGELOG.md | 3 +++ .../MSFT_AADConditionalAccessPolicy.psm1 | 12 ++++++------ .../MSFT_AADConditionalAccessPolicy.schema.mof | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c1febe3c9..6ba895ab13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ # UNRELEASED +* AADConditionalAccessPolicy + * Removed invalid empty string value that was added to the validate set + of two parameters. * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 index 7f3e7c076f..276bf4a184 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 @@ -71,7 +71,7 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -85,7 +85,7 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] @@ -755,7 +755,7 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -769,7 +769,7 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] @@ -1738,7 +1738,7 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -1752,7 +1752,7 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof index 9d1203c2af..67ec7174fa 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof @@ -16,10 +16,10 @@ class MSFT_AADConditionalAccessPolicy : OMI_BaseResource [Write, Description("AAD Admin Roles in scope of the Policy.")] String IncludeRoles[]; [Write, Description("AAD Admin Roles out of scope of the Policy.")] String ExcludeRoles[]; [Write, Description("Represents the Included internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String IncludeGuestOrExternalUserTypes[]; - [Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind; + [Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind; [Write, Description("Represents the Included collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String IncludeExternalTenantsMembers[]; [Write, Description("Represents the Excluded internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String ExcludeGuestOrExternalUserTypes[]; - [Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind; + [Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind; [Write, Description("Represents the Excluded collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String ExcludeExternalTenantsMembers[]; [Write, Description("Client Device Platforms in scope of the Policy.")] String IncludePlatforms[]; [Write, Description("Client Device Platforms out of scope of the Policy.")] String ExcludePlatforms[]; From b515483137b86b82ed6acf1f2d24e3e57a5d9a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20Kr=C3=BCger?= <15608729+andikrueger@users.noreply.github.com> Date: Wed, 14 Feb 2024 20:18:06 +0100 Subject: [PATCH 135/171] AADUser: Ensure: Absent logic seems wrong Fixes #4265 --- CHANGELOG.md | 3 ++ .../MSFT_AADUser/MSFT_AADUser.psm1 | 49 ++++++++++--------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b04ca09a5d..8b60b1e459 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. +* AADUser + * Fixed and issue where an user would be created even if the resrouce was set to absent. + FIXES [[#4265](https://github.com/microsoft/Microsoft365DSC/issues/4265)] * EXOMobileDeviceMailboxPolicy * Fixes an issue where an empty MinPasswordLength value was always passed down to the update logic flow. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 index e5756268a4..7f278519cb 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADUser/MSFT_AADUser.psm1 @@ -180,8 +180,8 @@ function Get-TargetResource } else { - Write-Verbose -Message "Retrieving user from the exported instances" - $user = $Script:M365DSCExportInstances | Where-Object -FilterScript {$_.UserPrincipalName -eq $UserPrincipalName} + Write-Verbose -Message 'Retrieving user from the exported instances' + $user = $Script:M365DSCExportInstances | Where-Object -FilterScript { $_.UserPrincipalName -eq $UserPrincipalName } } Write-Verbose -Message "Found User $($UserPrincipalName)" @@ -193,7 +193,7 @@ function Get-TargetResource } # return membership of static groups only - [array]$currentMemberOf = (Get-MgUserMemberOfAsGroup -UserId $UserPrincipalName -All | Where-Object -FilterScript {$_.GroupTypes -notcontains 'DynamicMembership'}).DisplayName + [array]$currentMemberOf = (Get-MgUserMemberOfAsGroup -UserId $UserPrincipalName -All | Where-Object -FilterScript { $_.GroupTypes -notcontains 'DynamicMembership' }).DisplayName $userPasswordPolicyInfo = $user | Select-Object UserprincipalName, @{ N = 'PasswordNeverExpires'; E = { $_.PasswordPolicies -contains 'DisablePasswordExpiration' } @@ -204,7 +204,7 @@ function Get-TargetResource { $Script:allDirectoryRoleAssignment = Get-MgBetaRoleManagementDirectoryRoleAssignment -All } - $assignedRoles = $Script:allDirectoryRoleAssignment | Where-Object -FilterScript {$_.PrincipalId -eq $user.Id} + $assignedRoles = $Script:allDirectoryRoleAssignment | Where-Object -FilterScript { $_.PrincipalId -eq $user.Id } $rolesValue = @() if ($null -eq $Script:allAssignedRoles -and $assignedRoles.Length -gt 0) @@ -213,7 +213,7 @@ function Get-TargetResource } foreach ($assignedRole in $assignedRoles) { - $currentRoleInfo = $Script:allAssignedRoles | Where-Object -FilterScript {$_.Id -eq $assignedRole.RoleDefinitionId} + $currentRoleInfo = $Script:allAssignedRoles | Where-Object -FilterScript { $_.Id -eq $assignedRole.RoleDefinitionId } $rolesValue += $currentRoleInfo.DisplayName } @@ -418,7 +418,7 @@ function Set-TargetResource Write-Verbose -Message "Removing User {$UserPrincipalName}" Remove-MgUser -UserId $UserPrincipalName } - else + elseif ($Ensure -eq 'Present') { $PasswordPolicies = $null if ($PasswordNeverExpires) @@ -498,7 +498,7 @@ function Set-TargetResource if ($null -ne $Password) { - Write-Verbose -Message "PasswordProfile property will not be updated" + Write-Verbose -Message 'PasswordProfile property will not be updated' } $CreationParams.Add('UserId', $UserPrincipalName) @@ -584,20 +584,20 @@ function Set-TargetResource if ($null -eq $group) { New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception "Attempting to add a user to a group that doesn't exist" ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -Exception "Attempting to add a user to a group that doesn't exist" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential throw "Group '$memberOfGroup' does not exist in tenant" } if ($group.GroupTypes -contains 'DynamicMembership') { New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception "Attempting to add a user to a dynamic group" ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -Exception 'Attempting to add a user to a dynamic group' ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential throw "Cannot add user $UserPrincipalName to group '$memberOfGroup' because it is a dynamic group" } @@ -615,20 +615,20 @@ function Set-TargetResource if ($null -eq $group) { New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception "Attempting to add a user to a group that doesn't exist" ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -Exception "Attempting to add a user to a group that doesn't exist" ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential throw "Group '$($_.InputObject)' does not exist in tenant" } if ($group.GroupTypes -contains 'DynamicMembership') { New-M365DSCLogEntry -Message 'Error updating data:' ` - -Exception "Attempting to add a user to a dynamic group" ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential + -Exception 'Attempting to add a user to a dynamic group' ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential throw "Cannot add user $UserPrincipalName to group '$($_.InputObject)' because it is a dynamic group" } @@ -914,7 +914,8 @@ function Export-TargetResource Property = $propertiesToRetrieve ErrorAction = 'Stop' } - if ($Filter -like "*endsWith*") { + if ($Filter -like '*endsWith*') + { $ExportParameters.Add('CountVariable', 'count') $ExportParameters.Add('ConsistencyLevel', 'eventual') } From 51b92a167c53cfa1fda2c902a13fd1b3c951e328 Mon Sep 17 00:00:00 2001 From: Fabien Tschanz Date: Wed, 14 Feb 2024 20:22:21 +0100 Subject: [PATCH 136/171] Fix AADRoleSetting DisplayName comparison --- CHANGELOG.md | 3 +++ .../MSFT_AADRoleSetting/MSFT_AADRoleSetting.psm1 | 16 ++++++++-------- .../MSFT_AADRoleSetting.schema.mof | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b04ca09a5d..8bd93ea1fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. +* AADRoleSetting + * Fix handling of DisplayName property in comparison + FIXES [#4019](https://github.com/microsoft/Microsoft365DSC/issues/4019) * EXOMobileDeviceMailboxPolicy * Fixes an issue where an empty MinPasswordLength value was always passed down to the update logic flow. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.psm1 index c179d662c8..ab1bd0536e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.psm1 @@ -194,7 +194,7 @@ function Get-TargetResource $ManagedIdentity ) - Write-Verbose -Message "Getting configuration of Role: $Displayname" + Write-Verbose -Message "Getting configuration of Role: $DisplayName" $ConnectionMode = New-M365DSCConnection -Workload 'MicrosoftGraph' ` -InboundParameters $PSBoundParameters @@ -225,7 +225,7 @@ function Get-TargetResource -ErrorAction SilentlyContinue } - if ($null -eq $RoleDefinition -and -not [System.String]::IsNullOrEmpty($Displayname)) + if ($null -eq $RoleDefinition -and -not [System.String]::IsNullOrEmpty($DisplayName)) { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { @@ -233,7 +233,7 @@ function Get-TargetResource } else { - $RoleDefinition = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq '$DisplayName'" + $RoleDefinition = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "displayName eq '$DisplayName'" } } @@ -327,7 +327,7 @@ function Get-TargetResource try { - Write-Verbose -Message "Found configuration of Rule $($Displayname)" + Write-Verbose -Message "Found configuration of Rule $($DisplayName)" $result = @{ Id = $Id DisplayName = $DisplayName @@ -587,7 +587,7 @@ function Set-TargetResource $ManagedIdentity ) - Write-Verbose -Message "Setting configuration of Role settings: $Displayname" + Write-Verbose -Message "Setting configuration of Role settings: $DisplayName" #Ensure the proper dependencies are installed in the current environment. Confirm-M365DSCDependencies @@ -602,7 +602,7 @@ function Set-TargetResource #endregion #get role - $RoleDefinition = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "DisplayName eq '$DisplayName'" + $RoleDefinition = Get-MgBetaRoleManagementDirectoryRoleDefinition -Filter "displayName eq '$DisplayName'" $Policy = $null if (-not [System.String]::IsNullOrEmpty($Id)) @@ -943,7 +943,7 @@ function Set-TargetResource else { #try with group - $Filter = "Displayname eq '" + $item + "'" + $Filter = "displayName eq '" + $item + "'" try { $group = Get-MgGroup -Filter $Filter -ErrorAction Stop @@ -1312,7 +1312,7 @@ function Test-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - Write-Verbose -Message "Testing configuration of Role Assignment: $Displayname" + Write-Verbose -Message "Testing configuration of Role Assignment: $DisplayName" $CurrentValues = Get-TargetResource @PSBoundParameters diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.schema.mof index 5a78b465fb..9239601277 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADRoleSetting/MSFT_AADRoleSetting.schema.mof @@ -1,7 +1,7 @@ [ClassVersion("1.0.0.0"), FriendlyName("AADRoleSetting")] class MSFT_AADRoleSetting : OMI_BaseResource { - [Key, Description("RuleDefinition Displayname")] String Displayname; + [Key, Description("RuleDefinition DisplayName")] String DisplayName; [Write, Description("Specifies the RoleId.")] String Id; [Write, Description("Activation maximum duration (hours).")] String ActivationMaxDuration; [Write, Description("Require justification on activation (True/False)")] Boolean ActivationReqJustification; From 62b663cccfe6d648a2fa65f0a08a320b3bdca979 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 14 Feb 2024 19:38:56 +0000 Subject: [PATCH 137/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md index bbeec98b03..d0da6f7b76 100644 --- a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md +++ b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md @@ -19,10 +19,10 @@ | **IncludeRoles** | Write | StringArray[] | AAD Admin Roles in scope of the Policy. | | | **ExcludeRoles** | Write | StringArray[] | AAD Admin Roles out of scope of the Policy. | | | **IncludeGuestOrExternalUserTypes** | Write | StringArray[] | Represents the Included internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue. | `none`, `internalGuest`, `b2bCollaborationGuest`, `b2bCollaborationMember`, `b2bDirectConnectUser`, `otherExternalUser`, `serviceProvider`, `unknownFutureValue` | -| **IncludeExternalTenantsMembershipKind** | Write | String | Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | ``, `all`, `enumerated`, `unknownFutureValue` | +| **IncludeExternalTenantsMembershipKind** | Write | String | Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | `all`, `enumerated`, `unknownFutureValue` | | **IncludeExternalTenantsMembers** | Write | StringArray[] | Represents the Included collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting. | | | **ExcludeGuestOrExternalUserTypes** | Write | StringArray[] | Represents the Excluded internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue. | `none`, `internalGuest`, `b2bCollaborationGuest`, `b2bCollaborationMember`, `b2bDirectConnectUser`, `otherExternalUser`, `serviceProvider`, `unknownFutureValue` | -| **ExcludeExternalTenantsMembershipKind** | Write | String | Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | ``, `all`, `enumerated`, `unknownFutureValue` | +| **ExcludeExternalTenantsMembershipKind** | Write | String | Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | `all`, `enumerated`, `unknownFutureValue` | | **ExcludeExternalTenantsMembers** | Write | StringArray[] | Represents the Excluded collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting. | | | **IncludePlatforms** | Write | StringArray[] | Client Device Platforms in scope of the Policy. | | | **ExcludePlatforms** | Write | StringArray[] | Client Device Platforms out of scope of the Policy. | | From b4e7d476f04653cd2490262a163192f4ac9ab5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20Kr=C3=BCger?= <15608729+andikrueger@users.noreply.github.com> Date: Wed, 14 Feb 2024 21:05:27 +0100 Subject: [PATCH 138/171] Terms of use: Agreement.Read.All and Agreement.ReadWrite.All are missing Fixes #3329 --- CHANGELOG.md | 2 ++ .../settings.json | 26 ++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ba895ab13..16d2b1ecb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * AADConditionalAccessPolicy * Removed invalid empty string value that was added to the validate set of two parameters. + * Updated permission reference for app-onlzy authentication. + FIXES [[#3329](https://github.com/microsoft/Microsoft365DSC/issues/3329)] * AADRoleEligibilityScheduleRequest * Fixed an issue where an error was thrown if no requests were found instead of simply returning the Null object. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json index 5d9c48c4c3..21929cd0e8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json @@ -52,16 +52,40 @@ }, "application": { "read": [ + { + "name": "Agreement.Read.All" + }, + { + "name": "Group.Read.All" + }, { "name": "Policy.Read.All" + }, + { + "name": "RoleManagement.Read.Directory" + }, + { + "name": "User.Read.All" } ], "update": [ { - "name": "Application.Read.All" + "name": "Agreement.Read.All" + }, + { + "name": "Group.Read.All" + }, + { + "name": "Policy.Read.All" }, { "name": "Policy.ReadWrite.ConditionalAccess" + }, + { + "name": "RoleManagement.Read.Directory" + }, + { + "name": "User.Read.All" } ] } From c5de137652353ad3dfde2fd8efe8608afae01cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20Kr=C3=BCger?= <15608729+andikrueger@users.noreply.github.com> Date: Wed, 14 Feb 2024 21:09:01 +0100 Subject: [PATCH 139/171] Added Application.Read.All to permission list --- .../MSFT_AADConditionalAccessPolicy/settings.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json index 21929cd0e8..bf18ad856d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/settings.json @@ -55,6 +55,9 @@ { "name": "Agreement.Read.All" }, + { + "name": "Application.Read.All" + }, { "name": "Group.Read.All" }, @@ -72,6 +75,9 @@ { "name": "Agreement.Read.All" }, + { + "name": "Application.Read.All" + }, { "name": "Group.Read.All" }, From 26abeb3b3dc4846fc862bf2b48782156974e2248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20Kr=C3=BCger?= <15608729+andikrueger@users.noreply.github.com> Date: Wed, 14 Feb 2024 21:19:54 +0100 Subject: [PATCH 140/171] SPOSharingSettings: Multiple sites returned from Get-PnPTenantSite Fixes #2759 --- CHANGELOG.md | 3 +++ .../MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ba895ab13..0ccb99ff9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,9 @@ * Fix typo in variable which made it export incorrectly and report that resource was not in correct state due to testing an incorrect value FIXES [#3972](https://github.com/microsoft/Microsoft365DSC/issues/3972) +* SPOSharingSettings + * Fixed an issue where the resource would return multiple sites. + FIXES [#2759](https://github.com/microsoft/Microsoft365DSC/issues/2759) * DEPENDENCIES * Updated DSCParser to version 1.4.0.2. * Updated Microsoft.Graph dependencies to version 2.13.1. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 index b8dd694459..b8c873870f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SPOSharingSettings/MSFT_SPOSharingSettings.psm1 @@ -520,7 +520,7 @@ function Set-TargetResource Set-PnPTenant @CurrentParameters | Out-Null if ($SetMySharingCapability) { - $mysite = Get-PnPTenantSite | Where-Object { $_.Url -match '-my.sharepoint.com/' } + $mysite = Get-PnPTenantSite | Where-Object { $_.Url -match '-my.sharepoint.com/' -and $_.Template -notmatch '^RedirectSite#' } Set-PnPTenantSite -Identity $mysite.Url -SharingCapability $MySiteSharingCapability } } From a60886faf4864242cdc010e5fd7faadcc3348871 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 14 Feb 2024 21:48:22 +0000 Subject: [PATCH 141/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md index d0da6f7b76..41ab4778b6 100644 --- a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md +++ b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md @@ -80,11 +80,11 @@ To authenticate with the Microsoft Graph API, this resource required the followi - **Read** - - Policy.Read.All + - Agreement.Read.All, Application.Read.All, Group.Read.All, Policy.Read.All, RoleManagement.Read.Directory, User.Read.All - **Update** - - Application.Read.All, Policy.ReadWrite.ConditionalAccess + - Agreement.Read.All, Application.Read.All, Group.Read.All, Policy.Read.All, Policy.ReadWrite.ConditionalAccess, RoleManagement.Read.Directory, User.Read.All ## Examples From ba2f2abd19bab328d52ea398249f173045103f9c Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 15 Feb 2024 00:55:26 +0000 Subject: [PATCH 142/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADRoleSetting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/resources/azure-ad/AADRoleSetting.md b/docs/docs/resources/azure-ad/AADRoleSetting.md index b79cc63f9e..efe34daf60 100644 --- a/docs/docs/resources/azure-ad/AADRoleSetting.md +++ b/docs/docs/resources/azure-ad/AADRoleSetting.md @@ -4,7 +4,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **Displayname** | Key | String | RuleDefinition Displayname | | +| **DisplayName** | Key | String | RuleDefinition DisplayName | | | **Id** | Write | String | Specifies the RoleId. | | | **ActivationMaxDuration** | Write | String | Activation maximum duration (hours). | | | **ActivationReqJustification** | Write | Boolean | Require justification on activation (True/False) | | From 12c08daa50ef769a5b61ce0b7234f79e5b91aeed Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 20:19:47 -0500 Subject: [PATCH 143/171] Various Telemetry Fixes --- CHANGELOG.md | 2 + .../Microsoft.ApplicationInsights.dll | Bin 313208 -> 385976 bytes .../Modules/M365DSCLogEngine.psm1 | 1 - .../Modules/M365DSCTelemetryEngine.psm1 | 69 +++--- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 203 +++++++++++------- 5 files changed, 168 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b04ca09a5d..ff5678b515 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ * Fix typo in variable which made it export incorrectly and report that resource was not in correct state due to testing an incorrect value FIXES [#3972](https://github.com/microsoft/Microsoft365DSC/issues/3972) +* SCDPLPCompianceRule + * Added support for multiple additional parameters. * DEPENDENCIES * Updated DSCParser to version 1.4.0.2. * Updated Microsoft.Graph dependencies to version 2.13.1. diff --git a/Modules/Microsoft365DSC/Dependencies/Microsoft.ApplicationInsights.dll b/Modules/Microsoft365DSC/Dependencies/Microsoft.ApplicationInsights.dll index acc3caca5b828876f052a6caf4c6fbcca4e9bfcd..3f8c8189e3d9a7583a95aa2042f4bbd5a34d3e1b 100644 GIT binary patch literal 385976 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 literal 313208 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 Rr>zH8+ucvQZ;OQh006Jl=N$k5 diff --git a/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 index 6514eb30e3..c74ae10c10 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCLogEngine.psm1 @@ -80,7 +80,6 @@ function New-M365DSCLogEntry #region Telemetry $driftedData = [System.Collections.Generic.Dictionary[[String], [String]]]::new() - $driftedData.Add('M365DSCOperation', 'Error') $driftedData.Add('CustomMessage', $Message) $driftedData.Add('Source', $Source) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 6dfd9325b1..040a59f077 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -20,7 +20,7 @@ function Get-M365DSCApplicationInsightsTelemetryClient if ($null -eq $InstrumentationKey) { - $InstrumentationKey = 'bc5aa204-0b1e-4499-a955-d6a639bdb4fa' + $InstrumentationKey = 'e670af5d-fd30-4407-a796-8ad30491ea7a' } $TelClient = [Microsoft.ApplicationInsights.TelemetryClient]::new() $TelClient.InstrumentationKey = $InstrumentationKey @@ -43,7 +43,7 @@ function Add-M365DSCTelemetryEvent param( [Parameter()] [System.String] - $Type = 'Flow', + $Type, [Parameter()] [System.Collections.Generic.Dictionary[[System.String], [System.String]]] @@ -191,6 +191,20 @@ function Add-M365DSCTelemetryEvent [array]$version = (Get-Module 'Microsoft365DSC').Version | Sort-Object -Descending $Data.Add('M365DSCVersion', $version[0].ToString()) + # OS Version + try + { + if ($null -eq $Global:M365DSCOSInfo) + { + $Global:M365DSCOSInfo = (Get-ComputerInfo -Property OSName -ErrorAction SilentlyContinue).OSName + } + $Data.Add('M365DSCOSVersion', $Global:M365DSCOSInfo) + } + catch + { + Write-Verbose -Message $_ + } + # LCM Metadata Information try { @@ -215,28 +229,31 @@ function Add-M365DSCTelemetryEvent $Data.Add('LCMState', $LCMInfo.LCMState) $Data.Add('LCMStateDetail', $LCMInfo.LCMStateDetail) - if ($Global:M365DSCExportInProgress) - { - $Data.Add('M365DSCOperation', 'Export') - } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') - { - $Data.Add('M365DSCOperation', 'MonitoringScheduled') - } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') + if ([System.String]::IsNullOrEMpty($Type)) { - $Data.Add('M365DSCOperation', 'MonitoringManual') - } - elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` - $LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') - { - $Data.Add('M365DSCOperation', 'ApplyingConfiguration') - } - else - { - $Data.Add('M365DSCOperation', 'Undetermined') + if ($Global:M365DSCExportInProgress) + { + $Type = 'Export' + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is performing a consistency check.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM exécute une vérification de cohérence.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM führt gerade eine Konsistenzüberprüfung durch.') + { + $Type = 'MonitoringScheduled' + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is testing node against the configuration.') + { + $Type = 'MonitoringManual' + } + elseif ($LCMInfo.LCMStateDetail -eq 'LCM is applying a new configuration.' -or ` + $LCMInfo.LCMStateDetail -eq 'LCM applique une nouvelle configuration.') + { + $Type = 'ApplyingConfiguration' + } + else + { + $Type = 'Undetermined' + } } } catch @@ -386,7 +403,7 @@ function Format-M365DSCTelemetryParameters try { $data.Add('Principal', $Parameters.Credential.UserName) - $data.Add('TenantId', $Parameters.Credential.UserName.Split('@')[1]) + $data.Add('Tenant', $Parameters.Credential.UserName.Split('@')[1]) } catch { @@ -396,11 +413,11 @@ function Format-M365DSCTelemetryParameters elseif ($Parameters.ApplicationId) { $data.Add('Principal', $Parameters.ApplicationId) - $data.Add('TenantId', $Parameters.TenantId) + $data.Add('Tenant', $Parameters.TenantId) } elseif (-not [System.String]::IsNullOrEmpty($TenantId)) { - $data.Add('TenantId', $Parameters.TenantId) + $data.Add('Tenant', $Parameters.TenantId) } $data.Add('ConnectionMode', (Get-M365DSCAuthenticationMode -Parameters $Parameters)) } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 846efd40bd..9fbf639bd1 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -913,7 +913,8 @@ function Test-M365DSCParameterState # If custom App Insights is specified, allow for the current and desired values to be captured; # ISSUE #1222 if ($null -ne $env:M365DSCTelemetryInstrumentationKey -and ` - $env:M365DSCTelemetryInstrumentationKey -ne 'bc5aa204-0b1e-4499-a955-d6a639bdb4fa') + $env:M365DSCTelemetryInstrumentationKey -ne 'bc5aa204-0b1e-4499-a955-d6a639bdb4fa' -and ` + $env:M365DSCTelemetryInstrumentationKey -ne 'e670af5d-fd30-4407-a796-8ad30491ea7a') { $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) @@ -1263,7 +1264,6 @@ function Export-M365DSCConfiguration #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() - $data.Add('M365DSCOperation', 'Extraction') $data.Add('Path', [System.String]::IsNullOrEmpty($Path)) $data.Add('FileName', $null -ne [System.String]::IsNullOrEmpty($FileName)) @@ -1301,7 +1301,7 @@ function Export-M365DSCConfiguration } } - Add-M365DSCTelemetryEvent -Data $data + Add-M365DSCTelemetryEvent -Type 'Export' -Data $data if ($null -ne $Workloads) { Write-Output -InputObject "Exporting Microsoft 365 configuration for Workloads: $($Workloads -join ', ')" @@ -1680,8 +1680,6 @@ function New-M365DSCConnection $SkipModuleReload = $false ) - $Global:MaximumFunctionCount = 32767 - if ($Workload -eq 'MicrosoftTeams') { try @@ -1711,7 +1709,14 @@ function New-M365DSCConnection #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Source', 'M365DSCUtil') - $data.Add('Platform', $Workload) + $data.Add('Workload', $Workload) + + # Keep track of workloads we already connected so that we don't send additional Telemetry events. + if ($null -eq $Script:M365ConnectedToWorkloads) + { + Write-Verbose -Message "Initializing the Connected To Workloads List." + $Script:M365ConnectedToWorkloads = @() + } # Get the ApplicationSecret parameter back as a string. if ($InboundParameters.ApplicationSecret) @@ -1725,7 +1730,6 @@ function New-M365DSCConnection { $message = 'Both Authentication methods are attempted' Write-Verbose -Message $message - $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = "You can't specify both the Credential and CertificateThumbprint" $data.Add('CustomMessage', $errorText) @@ -1742,7 +1746,6 @@ function New-M365DSCConnection $message = 'No Authentication method was provided' Write-Verbose -Message $message $message += "`r`nProvided Keys --> $($InboundParameters.Keys)" - $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = 'You must specify either the Credential or ApplicationId, TenantId and CertificateThumbprint parameters.' $data.Add('CustomMessage', $errorText) @@ -1761,22 +1764,26 @@ function New-M365DSCConnection Connect-M365Tenant -Workload $Workload ` -Credential $InboundParameters.Credential ` -SkipModuleReload $Global:CurrentModeIsExport - $data.Add('ConnectionType', 'Credential') - try + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-Credential") { - if (-not $Data.ContainsKey('Tenant')) + $data.Add('ConnectionType', 'Credential') + try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } + } + catch + { + Write-Verbose -Message $_ } - } - catch - { - Write-Verbose -Message $_ - } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-Credential" + } return 'Credentials' } if ($InboundParameters.ContainsKey('Credential') -and @@ -1786,22 +1793,25 @@ function New-M365DSCConnection -Credential $InboundParameters.Credential ` -Url $Url ` -SkipModuleReload $Global:CurrentModeIsExport - $data.Add('ConnectionType', 'Credential') - - try + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-Credential") { - if (-not $Data.ContainsKey('Tenant')) + $data.Add('ConnectionType', 'Credential') + try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } + } + catch + { + Write-Verbose -Message $_ } - } - catch - { - Write-Verbose -Message $_ - } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-Credential" + } return 'Credentials' } } @@ -1817,22 +1827,26 @@ function New-M365DSCConnection -ApplicationId $InboundParameters.ApplicationId ` -Credential $InboundParameters.Credential ` -SkipModuleReload $Global:CurrentModeIsExport - $data.Add('ConnectionType', 'CredentialsWithApplicationId') - - try + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-CredentialsWithApplicationId") { - if (-not $Data.ContainsKey('Tenant')) + $data.Add('ConnectionType', 'CredentialsWithApplicationId') + + try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } + } + catch + { + Write-Verbose -Message $_ } - } - catch - { - Write-Verbose -Message $_ - } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-CredentialsWithApplicationId" + } return 'CredentialsWithApplicationId' } else @@ -1842,22 +1856,26 @@ function New-M365DSCConnection -Credential $InboundParameters.Credential ` -Url $Url ` -SkipModuleReload $Global:CurrentModeIsExport - $data.Add('ConnectionType', 'CredentialsWithApplicationId') - - try + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-CredentialsWithApplicationId") { - if (-not $Data.ContainsKey('Tenant')) + $data.Add('ConnectionType', 'CredentialsWithApplicationId') + + try { - $tenantId = $InboundParameters.Credential.Username.Split('@')[1] - $data.Add('Tenant', $tenantId) + if (-not $Data.ContainsKey('Tenant')) + { + $tenantId = $InboundParameters.Credential.Username.Split('@')[1] + $data.Add('Tenant', $tenantId) + } + } + catch + { + Write-Verbose -Message $_ } - } - catch - { - Write-Verbose -Message $_ - } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-CredentialsWithApplicationId" + } return 'CredentialsWithApplicationId' } } @@ -1878,12 +1896,16 @@ function New-M365DSCConnection -CertificatePath $InboundParameters.CertificatePath ` -SkipModuleReload $Global:CurrentModeIsExport - $data.Add('ConnectionType', 'ServicePrincipalWithPath') - if (-not $data.ContainsKey('Tenant')) + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ServicePrincipalWithPath") { - $data.Add('Tenant', $InboundParameters.TenantId) + $data.Add('ConnectionType', 'ServicePrincipalWithPath') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-ServicePrincipalWithPath" } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithPath' } #endregion @@ -1897,7 +1919,6 @@ function New-M365DSCConnection $message = 'No Authentication method was provided' Write-Verbose -Message $message $message += "`r`nProvided Keys --> $($InboundParameters.Keys)" - $data.Add('M365DSCOperation', 'Error') $data.Add('Exception', $message) $errorText = 'You must specify either the Credential or ApplicationId, TenantId and CertificateThumbprint parameters.' $data.Add('CustomMessage', $errorText) @@ -1938,13 +1959,16 @@ function New-M365DSCConnection -ApplicationSecret $InboundParameters.ApplicationSecret ` -SkipModuleReload $Global:CurrentModeIsExport - - $data.Add('ConnectionType', 'ServicePrincipalWithSecret') - if (-not $data.ContainsKey('Tenant')) + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ServicePrincipalWithSecret") { - $data.Add('Tenant', $InboundParameters.TenantId) + $data.Add('ConnectionType', 'ServicePrincipalWithSecret') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-ServicePrincipalWithSecret" } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithSecret' } else @@ -1956,13 +1980,16 @@ function New-M365DSCConnection -Url $Url ` -SkipModuleReload $Global:CurrentModeIsExport - - $data.Add('ConnectionType', 'ServicePrincipalWithSecret') - if (-not $data.ContainsKey('Tenant')) + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ServicePrincipalWithSecret") { - $data.Add('Tenant', $InboundParameters.TenantId) + $data.Add('ConnectionType', 'ServicePrincipalWithSecret') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-ServicePrincipalWithSecret" } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithSecret' } } @@ -1975,13 +2002,16 @@ function New-M365DSCConnection -CertificateThumbprint $InboundParameters.CertificateThumbprint ` -SkipModuleReload $Global:CurrentModeIsExport ` -Url $Url - - $data.Add('ConnectionType', 'ServicePrincipalWithThumbprint') - if (-not $data.ContainsKey('Tenant')) + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ServicePrincipalWithThumbprint") { - $data.Add('Tenant', $InboundParameters.TenantId) + $data.Add('ConnectionType', 'ServicePrincipalWithThumbprint') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-ServicePrincipalWithThumbprint" } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ServicePrincipalWithThumbprint' } # Case only the TenantId and Credentials parameters are specified @@ -1993,6 +2023,16 @@ function New-M365DSCConnection -Credential $InboundParameters.Credential ` -Url $Url ` -SkipModuleReload $Global:CurrentModeIsExport + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-CredentialsWithTenantId") + { + $data.Add('ConnectionType', 'CredentialsWithTenantId') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-CredentialsWithTenantId" + } return "CredentialsWithTenantId" } # Case only Managed Identity and TenantId are specified @@ -2005,13 +2045,16 @@ function New-M365DSCConnection -TenantId $InboundParameters.TenantId ` -SkipModuleReload $Global:CurrentModeIsExport - - $data.Add('ConnectionType', 'ManagedIdentity') - if (-not $data.ContainsKey('Tenant')) + if (-not $Script:M365ConnectedToWorkloads -contains "$Workload-ManagedIdentity") { - $data.Add('Tenant', $InboundParameters.TenantId) + $data.Add('ConnectionType', 'ManagedIdentity') + if (-not $data.ContainsKey('Tenant')) + { + $data.Add('Tenant', $InboundParameters.TenantId) + } + Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' + $Script:M365ConnectedToWorkloads += "$Workload-ManagedIdentity" } - Add-M365DSCTelemetryEvent -Data $data -Type 'Connection' return 'ManagedIdentity' } else From d8c36b9a81801845418b19b03f8318e98fcc2960 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 20:34:24 -0500 Subject: [PATCH 144/171] Release 1.24.214.1 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 76 ++++++++++++++------ 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76b4e7bcb1..35b086367c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.214.1 * AADConditionalAccessPolicy * Removed invalid empty string value that was added to the validate set diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index b45581ddf2..54cd36eb6e 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-08 +# Generated on: 2024-02-14 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.207.2' + ModuleVersion = '1.24.214.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -140,25 +140,61 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* TeamsAppSetupPolicy - * Changed the logic to retrieve arrays of Ids in the Get method. - * MISC - * Drift Logging - * Now includes the full list of parameters for the current values. - * Telemetry - * Added a new M365DSCTelemetryEventId parameter to track duplication of events. - * IntuneDeviceEnrollmentPlatformRestriction - * Added Priority parameter - FIXES [#4081](https://github.com/microsoft/Microsoft365DSC/issues/4081) - * SCDLPComplianceRule - * Properly escapes fancy quotes in the Get method. - * TeamsMeetingPolicy - * Ignore the AllowUserToJoinExternalMeeting parameterfor drift evaluation - since it doesnt do anything based on official documentation. + ReleaseNotes = '* AADConditionalAccessPolicy + * Removed invalid empty string value that was added to the validate set + of two parameters. + * Updated permission reference for app-onlzy authentication. + FIXES [[#3329](https://github.com/microsoft/Microsoft365DSC/issues/3329)] + * AADRoleEligibilityScheduleRequest + * Fixed an issue where an error was thrown if no requests were found instead + of simply returning the Null object. + * AADRoleSetting + * Fix handling of DisplayName property in comparison + FIXES [#4019](https://github.com/microsoft/Microsoft365DSC/issues/4019) + * AADUser + * Fixed and issue where an user would be created even if the resrouce was set to absent. + FIXES [[#4265](https://github.com/microsoft/Microsoft365DSC/issues/4265)] + * EXOMobileDeviceMailboxPolicy + * Fixes an issue where an empty MinPasswordLength value was always passed down + to the update logic flow. + * IntuneAppConfigurationPolicy + * Added parameter Id to avoid having to retrieve the same policy multiple + times + * Fixed tests in Test-TargetResource to ensure the resource reports its + correct state + FIXES [#3542](https://github.com/microsoft/Microsoft365DSC/issues/3542) + * IntuneDeviceAndAppManagementAssignmentFilter + * Fixed Test-TargetResource to ensure that resource reports its correct state + FIXES [#3959](https://github.com/microsoft/Microsoft365DSC/issues/3959) + * IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10 + * Fixed Test-TargetResource by removing Id from being tested and also used + correct filter while retrieving the policy otherwise it could not be found + FIXES [#3964](https://github.com/microsoft/Microsoft365DSC/issues/3964) + * IntuneDeviceConfigurationPolicyAndroidWorkProfile + * Fix typo in variable which made it export incorrectly and report that + resource was not in correct state due to testing an incorrect value + FIXES [#3972](https://github.com/microsoft/Microsoft365DSC/issues/3972) + * IntuneSettingCatalogASRRulesPolicyWindows10 + * Fix removal of resource if Identity comes from another tenant or is not + present in blueprint + * Fix Test-TargetResource by not comparing Identity since it might be from + another tenant or not present in blueprint + FIXES [#4302](https://github.com/microsoft/Microsoft365DSC/issues/4302) + * SCDPLPCompianceRule + * Added support for multiple additional parameters. + * SPOSharingSettings + * Fixed an issue where the resource would return multiple sites. + FIXES [#2759](https://github.com/microsoft/Microsoft365DSC/issues/2759) * DEPENDENCIES - * Updated Microsoft.PowerApps.Administration.PowerShell to version 2.0.180. - * Updated MSCloudLoginAssistant to version 1.1.11 - * Updated ReverseDSC to version 2.0.0.19' + * Updated DSCParser to version 1.4.0.2. + * Updated Microsoft.Graph dependencies to version 2.13.1. + * Updated MSCloudLoginAssistant to version 1.1.13. + * MISC + * M365DSCReport + * Fix nested change detection for CIMInstances + * Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report + FIXES [#4291](https://github.com/microsoft/Microsoft365DSC/issues/4291) + * Added new QA test to check for missing description in resource schema' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 7788013a5fe06ab2153bf751b8707e2c6deba47a Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 20:53:56 -0500 Subject: [PATCH 145/171] Release 1.24.214.2 --- CHANGELOG.md | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 2 +- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35b086367c..880bdd44b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# 1.24.214.1 +# 1.24.214.2 * AADConditionalAccessPolicy * Removed invalid empty string value that was added to the validate set diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 54cd36eb6e..6e3fad6c64 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.214.1' + ModuleVersion = '1.24.214.2' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9fbf639bd1..6c6baf3a4c 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -919,7 +919,7 @@ function Test-M365DSCParameterState $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) } - if (-not $Data.ContainsKey('Tenant')) + if (-not $driftedData.ContainsKey('Tenant')) { $driftedData.Add('Tenant', $TenantName) } From 20c3484e129d10ad971e80013d017d225adc3190 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 20:59:54 -0500 Subject: [PATCH 146/171] Update M365DSCUtil.psm1 --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 6c6baf3a4c..4599510931 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -921,6 +921,7 @@ function Test-M365DSCParameterState } if (-not $driftedData.ContainsKey('Tenant')) { + $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues $driftedData.Add('Tenant', $TenantName) } $driftedData.Add('Resource', $source.Split('_')[1]) @@ -929,16 +930,6 @@ function Test-M365DSCParameterState $EventMessage.Append(" " + $DriftedParameters.$key + "`r`n") | Out-Null } - #region Telemetry - $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues - $data.Add('Event', 'ConfigurationDrift') - - if (-not $Data.ContainsKey('Tenant')) - { - $data.Add('Tenant', $TenantName) - } - #endregion - $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null From 862727ff70305d1ab15bf502c56c36684bd5d322 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 14 Feb 2024 21:03:38 -0500 Subject: [PATCH 147/171] Update M365DSCUtil.psm1 --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 4599510931..5f2d308de4 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -919,11 +919,8 @@ function Test-M365DSCParameterState $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) } - if (-not $driftedData.ContainsKey('Tenant')) - { - $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues - $driftedData.Add('Tenant', $TenantName) - } + $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues + $driftedData.Add('Tenant', $TenantName) $driftedData.Add('Resource', $source.Split('_')[1]) Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData #endregion From 0fa3f71028e160cbf77c7e9ffa32ede07d917e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Albeck?= <61009084+salbeck-sit@users.noreply.github.com> Date: Thu, 15 Feb 2024 09:09:23 +0100 Subject: [PATCH 148/171] Update Uninstall-M365OutdatedDependencies older versions of the Microsoft365DSC-module is now deleted in their entirety instead of just the manifest. --- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 9fbf639bd1..c6763e2820 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -2949,7 +2949,7 @@ function Uninstall-M365DSCOutdatedDependencies Write-Information -MessageData "Uninstalling $($module.Name) Version {$($module.Version)}" if (Test-Path -Path $($module.Path)) { - Remove-Item $($module.Path) -Force -Recurse + Remove-Item $($module.ModuleBase) -Force -Recurse } } catch From 460abd1acc0493ba4803da1b1bd399c1cccd0908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Albeck?= <61009084+salbeck-sit@users.noreply.github.com> Date: Thu, 15 Feb 2024 09:10:43 +0100 Subject: [PATCH 149/171] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35b086367c..acb20dd4da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change log for Microsoft365DSC +# Unreleased +* MISC + * Uninstall-M365DSCOutdatedDependencies + * Outdated Microsoft365DSC-modules are now removed in their entirety + # 1.24.214.1 * AADConditionalAccessPolicy From ca1e6330994d4e1f78059670a872e71674e74e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20Kr=C3=BCger?= <15608729+andikrueger@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:33:27 +0100 Subject: [PATCH 150/171] fixed some documentation typos --- .../get-started/authentication-and-permissions.md | 13 +++++++++---- .../user-guide/get-started/monitoring-drifts.md | 1 + .../user-guide/get-started/powershell7-support.md | 14 +++++++------- docs/docs/user-guide/get-started/prerequisites.md | 8 ++++++++ .../get-started/snapshot-of-existing-tenant.md | 15 ++++++++++++++- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/docs/docs/user-guide/get-started/authentication-and-permissions.md b/docs/docs/user-guide/get-started/authentication-and-permissions.md index e61a750122..77ce686d01 100644 --- a/docs/docs/user-guide/get-started/authentication-and-permissions.md +++ b/docs/docs/user-guide/get-started/authentication-and-permissions.md @@ -54,7 +54,7 @@ In order to authenticate to Power Apps using a Service Principal (Certificate Th Additionally, to be able to authenticate using a Certificate Thumbprint, the underlying Power Apps PowerShell module used by Microsoft365DSC requires the certificate's private key (.pfx) to be registered under the current user's certificate store at Cert:\CurrentUser\My\. Omitting to register the private key will result in Microsoft365DSC throwing the following error when trying to authenticate to the Power Platform: -``` +```powershell Get-Item: Cannot find path 'Cert:\CurrentUser\My\****************************************' because it does not exist. ``` @@ -174,14 +174,16 @@ SharePoint Online uses the legacy ACS model to authenticate using an Application 3. In the App domain box, type in www..com. 4. Leave the **Redirect URL** box empty. 5. In the **Permission request XML** box, put in the following XML: -``` + +```powershell ``` + 6. Click on the **Create** button. Register a new app for SharePoint Online. -7. On the next screen, click on the ** Trust It** button to complete the registration process. +7. On the next screen, click on the **Trust It** button to complete the registration process. Register a new app for SharePoint Online. You should now be able to connect to SharePoint Online using an Application Secret. @@ -217,10 +219,11 @@ If you want to leverage Service Principal Authentication (using an App Registrat PowerShell Script to create a service principal -``` powershell +```powershell $App = Get-MgApplication -Filter "DisplayName eq 'MySCApp'" New-ServicePrincipal -AppId $App.AppId -ServiceId $App.Id -DisplayName "SC-SPN" ``` +
  • Grant the eDiscovery Manager role to your new Service Principal:

    @@ -232,6 +235,7 @@ New-ServicePrincipal -AppId $App.AppId -ServiceId $App.Id -DisplayName "SC-SPN" $SPN = Get-ServicePrincipal -Identity "SC-SPN" Add-RoleGroupMember -Identity eDiscoveryManager -Member $SPN.ObjectId ``` +
  • @@ -245,6 +249,7 @@ Add-RoleGroupMember -Identity eDiscoveryManager -Member $SPN.ObjectId $SPN = Get-ServicePrincipal -Identity "SC-SPN" Add-eDiscoveryCaseAdmin -User $SPN.Name ``` +

  • Grant your app registration the Compliance Administrator role:

    diff --git a/docs/docs/user-guide/get-started/monitoring-drifts.md b/docs/docs/user-guide/get-started/monitoring-drifts.md index 7a120f1bd1..5c76dbc8c0 100644 --- a/docs/docs/user-guide/get-started/monitoring-drifts.md +++ b/docs/docs/user-guide/get-started/monitoring-drifts.md @@ -1,6 +1,7 @@ Once a configuration has been applied to a Microsoft 365 tenant using Microsoft365DSC, the local system will perform regular checks to analyze the configuration of the remote tenant against what its desired state should be and detect any configuration drifts. This feature comes from PowerShell DSC out-of-the-box and is not something specific to Microsoft365DSC. By default the DSC engine on the system where the configuration was applied from will check for configuration drifts every 15 minutes. ## Microsoft365DSC Event log + If a drift in configuration is detected, Microsoft365DSC will log it in Event Viewer on the machine. Detected drifts will get logged under the **M365DSC** log journal in Event Viewer. Microsoft365DSC provide very detailed entries in event viewer that help you identify exactly in what component a drift was detected as well as what property was detected to have drifted.
    diff --git a/docs/docs/user-guide/get-started/powershell7-support.md b/docs/docs/user-guide/get-started/powershell7-support.md index 5b699bac5b..cb869406b4 100644 --- a/docs/docs/user-guide/get-started/powershell7-support.md +++ b/docs/docs/user-guide/get-started/powershell7-support.md @@ -4,12 +4,12 @@ While Microsoft365DSC supports running PowerShell 7+, there are a few things tha Microsoft365DSC currently requires dependencies to be installed under the C:\Program Files\WindowsPowerShell\Modules folders. Having the dependencies installed anywhere else can cause issues loading modules. The recommendation here is to use PowerShell 5.1 to install the Module using: -``` +```powershell Install-Module Microsoft365DSC -Force Update-M365DSCModule ``` -Then flip to PowerShell 7+ once the prerequesite modules are properly installed under C:\Program Files\WindowsPowerShell\Modules. +Then flip to PowerShell 7+ once the prerequisite modules are properly installed under C:\Program Files\WindowsPowerShell\Modules. ## Common Issues When the Modules are Not in the Right Folder @@ -17,7 +17,7 @@ Then flip to PowerShell 7+ once the prerequesite modules are properly installed The module that is ensuring the proper encoding of the exported DSC content relies on the Get-DscResource cmdlet to cache information about the resources' properties and is a way to improve performance. If the Microsoft365DSC module is not located under the Windows PowerShell folder, every instance extracted by the Export process will throw the following error: -``` +```powershell WARNING: There are no modules present in the system with the given module specification. ``` @@ -25,15 +25,15 @@ To solve this, make sure the Microsoft365DSC is properly installed under C:\Prog **Issues loading the PnP.PowerShell Module** -The PnP.PowerShell module, which is currently being used by the SharePoint Online and OndeDrive for Business workloads needs to be loaded using Windows PowerShell. In PowerShell 7+, this is done by running the **Import-Module** cmdlet using the **-UseWindowsPowerShell** switch, and requires the modules to be located under C:\Program Files\WindowsPowerShell. In order for Microsoft365DSC to work for SharePoint Online and OneDrive for Business with PowerShell 7, you need to make sure that the PnP.PowerShell module is located under C:\Program Files\WindowsPowerShell\Modules\PnP.PowerShell. This can be achieved by either manually moving the module to that location, or by using PowerShell 5.1 to install it using the following line: +The PnP.PowerShell module, which is currently being used by the SharePoint Online and OneDrive for Business workloads needs to be loaded using Windows PowerShell. In PowerShell 7+, this is done by running the **Import-Module** cmdlet using the **-UseWindowsPowerShell** switch, and requires the modules to be located under C:\Program Files\WindowsPowerShell. In order for Microsoft365DSC to work for SharePoint Online and OneDrive for Business with PowerShell 7, you need to make sure that the PnP.PowerShell module is located under C:\Program Files\WindowsPowerShell\Modules\PnP.PowerShell. This can be achieved by either manually moving the module to that location, or by using PowerShell 5.1 to install it using the following line: -``` +```powershell Install-Module PnP.PowerShell -Force -Scope AllUsers ``` The reason why this module needs to be loaded using WindowsPowerShell is because it tries to load its own version of the System.IdentityModel.Tokens assembly, which conflicts with the one used by the Microsoft.Graph.Authentication module. Microsoft365DSC often requires both modules to be loaded at the same time, which causes a conflict. By using the -UseWindowsPowerShell switch, we load the PnP.PowerShell module into its own separate runspace, which avoids the assembly conflicts. Having the PnP module installed under any path other than the Windows PowerShell one can result in one of the issues listed below: -``` +```powershell Exception: Powershell 7+ was detected. We need to load the PnP.PowerShell module using the -UseWindowsPowerShell switch which requires the module to be installed under C:\Program Files\WindowsPowerShell\Modules. You can either move the module to that location or use PowerShell 5.1 to install the modules using 'Install-Module Pnp.PowerShell -Force -Scope AllUsers'. @@ -45,6 +45,6 @@ Connect-PnPOnline: Could not load file or assembly 'System.IdentityModel.Tokens. Starting with PowerShell 7.2, the core Desired State Configuration module (PSdesiredStateConfiguration) has been decoupled from the core PowerShell build and now need to be installed separately. In a PowerShell 7+ console, you can install the module by running the command: -``` +```powershell Install-Module PSDesiredStateConfiguration -Force ``` diff --git a/docs/docs/user-guide/get-started/prerequisites.md b/docs/docs/user-guide/get-started/prerequisites.md index dbb7bc3282..0ff30b9b23 100644 --- a/docs/docs/user-guide/get-started/prerequisites.md +++ b/docs/docs/user-guide/get-started/prerequisites.md @@ -1,18 +1,23 @@ ## Technical requirements + For Microsoft365DSC to function, you need to arrange the following components: ### PowerShell version + Microsoft365DSC is supported for PowerShell version 5.1 and 7.3+. For additional details on how to leverage it with PowerShell 7, please refer to our [PowerShell 7+ Guide for Microsoft365DSC](https://microsoft365dsc.com/user-guide/get-started/powershell7-support/). ### Tooling + To get the best experience running Microsoft365DSC cmdlets, it is recommended that you use the Windows Terminal. All screenshots provided in this article are using the Windows Terminal. This tool allows you to quickly switch between PowerShell versions and provide better support for icons and symbols that are used throughout Microsoft365DSC’s experience. ### Permissions + In order to connect to Microsoft 365, you need to make sure you have valid credentials (user **or** application credentials) with the correct permissions to the Microsoft 365 service. Microsoft365DSC offers several methods of authentication, depending on the used resources. Unfortunately, we are depending on the supported authentication methods used by the various PowerShell modules that are used. Make sure you review the [Authentication and Permissions](../authentication-and-permissions) article for more information on the available authentication methods and how to configure all required permissions. ## Experience and skills + Before you start using Microsoft365DSC, it is important that you also have the proper experience and skills on administering Microsoft 365. Microsoft365DSC is a powerful solution that can greatly streamline Microsoft 365 administration. But with great power comes great responsibility: **If you don't know what exactly you are doing, using Microsoft365DSC you can also cause some serious damage.** @@ -34,16 +39,19 @@ Additionally it can be helpful, depending on the planned use of Microsoft365DSC, You can review the following training resources and certifications, for learning more about the above topics: #### PowerShell Desired State Configuration + - Get started with Desired State Configuration for Windows - Separating configuration and environment data - Video series: "Getting Started with PowerShell Desired State Configuration" #### Microsoft 365 Administration + - About the Microsoft 365 admin center - Overview of the Microsoft 365 admin center - About admin roles - Video: Get an overview of the Microsoft 365 admin center #### Recommended Certification + - Microsoft 365 Certified: Fundamentals (MS-900) - Microsoft 365 Certified: Enterprise Administrator Expert (MS-100 & MS-101) diff --git a/docs/docs/user-guide/get-started/snapshot-of-existing-tenant.md b/docs/docs/user-guide/get-started/snapshot-of-existing-tenant.md index 49c28a70cb..317bd62603 100644 --- a/docs/docs/user-guide/get-started/snapshot-of-existing-tenant.md +++ b/docs/docs/user-guide/get-started/snapshot-of-existing-tenant.md @@ -6,13 +6,13 @@ In previous versions of the module, simply running the above cmdlet would automa Initiating the snapshot process via the **Export-M365DSCConfiguration** cmdlet will begin by authenticating against all required workloads. The first thing it will do is compile a list of all components it is about to capture and figure out what workload they are part of. Then it will automatically authenticated against each one using the authentication parameters provided. ## Web Based User Interface + While the default process has changed with recent versions of the module, you can still use a newly revamped, web-based User Interface to help you build the PowerShell command to execute based on the components you wish to capture. To launch this new web interface, simply use the **-LaunchWebUI** switch when calling the Export-M365DSCConfiguration cmdlet. This will automatically launch a new web browser interface and navigate you to https://export.microsoft365dsc.com
    ![Screenshot of the Microsoft365DSC Export site](../../Images/ExportGUI.png)
    The Microsoft365DSC Export generator
    - On the web page, simply select the components you want to export and click on the **Generate** button at the top right. This will open a new prompt that will allow you to copy the PowerShell command you need to run to capture a snapshot of the selected components via Microsoft365DSC. Simply copy this command and paste it in your PowerShell console to initiate the capture process.
    @@ -21,6 +21,7 @@ On the web page, simply select the components you want to export and click on th
    ## Unattended Capture + As mentioned above, Microsoft365DSC now defaults to an unattended capture process when running the **Export-M365DSCConfiguration** cmdlet. To quickly get started, simply open a new PowerShell console and run the cmdlet. By default, if you don’t provide any additional parameters to the cmdlet, it will try to use credentials to authenticate against the various workloads. In the case where no additional authentication parameters are provided, Microsoft365DSC will prompt you for credentials and will use those credentials to authenticate throughout the capture process.
    @@ -46,6 +47,7 @@ Export-M365DSCConfiguration -Credential $creds
    ### Running An Export Using Service Principal + The same process applies if you are trying to authenticate using a Service Principal. In this case you would need to pass in the ApplicationID and TenantID parameter and decide whether to use an Application Secret or a Certificate Thumbprint.
    @@ -87,9 +89,11 @@ It is also important to note, the resulting file will always contain random GUID
    ## Available Parameters + The Microsoft365DSC tenant configuration snapshot feature offers several options you can use to better control the output capture. This section provides an overview of each additional parameter that is available for the **Export-M365DSCConfiguration** cmdlet and how they can be used during the capture process ### LaunchWebUI + As mentioned above, the moment this switch is present when calling the **Export-M365DSCConfiguration** cmdlet it will launch new browser window and navigate to the export user interface at https://export.microsoft365dsc.com. ```PowerShell @@ -97,6 +101,7 @@ Export-M365DSCConfiguration -LaunchWebUI ``` ### Components + This parameter accepts an array containing the names of the components you want to capture as part of your snapshot. Omitting this parameter will default the capture process to capture all components that are part of the default components list (see parameter **Mode**).
    @@ -105,6 +110,7 @@ This parameter accepts an array containing the names of the components you want
    ### ConfigurationName + This parameter allows you to specify how the DSC configuration object, inside of the exported configuration file will be named.
    @@ -115,6 +121,7 @@ This parameter allows you to specify how the DSC configuration object, inside of Omitting to specify this parameter will result in the configuration object to be named as the file’s name (e.g. M365TenantConfig). ### FileName + This allows you to specify how you wish the resulting file to be named. Specify the name of the file, including the extension (e.g. .ps1).
    @@ -125,6 +132,7 @@ This allows you to specify how you wish the resulting file to be named. Specify Omitting to specify this parameter will name the resulting file as M365TenantConfig.ps1 ### Filters + This allows you to specify a filter at the resource level to reduce the overall instances that are being extracted. As an example, if you are only interested in extracting Azure AD Groups that have their display name start with the word 'Microsoft', you could specify the following filters: ``` @@ -139,6 +147,7 @@ $Filters = @{
    ### GenerateInfo + This parameter allows users to specify whether or not comments should be added as part of the exported file to provide additional information about the various types of components captured.
    ![Example of specifying whether to generate additional information](../../Images/ExportGenerateInfo.png) @@ -146,6 +155,7 @@ This parameter allows users to specify whether or not comments should be added a
    ### MaxProcesses + There are a few components inside of Microsoft365DSC for which parallelism has been implemented as part of their snapshot process to improve speed. This parameter allows user to specify how many parallel threads should be created during the capture process. Components leveraging parallelism are: SPOPropertyBag, SPOUserProfileProperty and TeamsUser. The specified value for this parameter has to be between **1** and **100**. Instances of the components will be equally divided amongst the various threads.
    @@ -161,6 +171,7 @@ There are a few components inside of Microsoft365DSC for which parallelism has b While there are advantages to implementing multithreading for the snapshot process, there are many disadvantages as well such as not being able to properly view ongoing progress inside threads and added complexity to the design of the resources. After weighting in the pros can cons of implementing this approach across all components to speed up the entire capture process, we’ve opted to keep the design of the resources simpler (no use parallelism) for maintenance purposes and to ensure users have a consistent way of view progress during the snapshot process. ### Mode + This parameter allows users to specify what set of components they wish to capture as part of their snapshot process. By default, Microsoft365DSC will exclude some components from the capture process either because these are likely to take a very long time to export (e.g. SPOPropertyBag) or that they are more related to data than actual configuration settings (e.g. Planner Tasks, SPOUserProfileProperty, etc.). Available modes are: - Lite @@ -178,6 +189,7 @@ To keep track of what resources are available in what mode, Microsoft365DSC defi This means that the **Lite** extraction mode will contain all resources with the exception of those listed in Default and Full. The **Default** mode will include all resources from the Lite mode, plus the SPOApp and SPOSiteDesign components, and **Full** will include every resource available in the project. ### Path + This parameter allows you to specify the location where the resulting file will be stored. Omitting to specify this parameter will prompt the user to provide the destination path at the end of the capture process.
    @@ -186,6 +198,7 @@ This parameter allows you to specify the location where the resulting file will
    ### Workloads + This parameter accepts an array containing the names of various workloads you wish to capture the components for as part of your snapshot process. Users need to specify the acronym of the workloads, which can be any of: - **AAD** – Azure Active Directory From 9d212f3fc1fa9b2855afa0bf8e40f1be4dd3e94d Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 15 Feb 2024 06:53:39 -0500 Subject: [PATCH 151/171] Fixes for Telemetry --- .../MSFT_AADApplication.psm1 | 6 --- .../Modules/M365DSCTelemetryEngine.psm1 | 2 + .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 45 ++++++++++--------- 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 0fb97b0d94..418aefd556 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -806,12 +806,6 @@ function Test-TargetResource $ValuesToCheck.Remove('ObjectId') | Out-Null $ValuesToCheck.Remove('AppId') | Out-Null $ValuesToCheck.Remove('Permissions') | Out-Null - $ValuesToCheck.Remove('ApplicationId') | Out-Null - $ValuesToCheck.Remove('Credential') | Out-Null - $ValuesToCheck.Remove('TenantId') | Out-Null - $ValuesToCheck.Remove('ApplicationSecret') | Out-Null - $ValuesToCheck.Remove('CertificateThumbprint') | Out-Null - $ValuesToCheck.Remove('ManagedIdentity') | Out-Null $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` -Source $($MyInvocation.MyCommand.Source) ` diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 040a59f077..47a4fdcedb 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -53,6 +53,7 @@ function Add-M365DSCTelemetryEvent [System.Collections.Generic.Dictionary[[System.String], [System.Double]]] $Metrics ) + $verbosepreference = 'continue' $TelemetryEnabled = [System.Environment]::GetEnvironmentVariable('M365DSCTelemetryEnabled', ` [System.EnvironmentVariableTarget]::Machine) @@ -70,6 +71,7 @@ function Add-M365DSCTelemetryEvent $Data.Add('ProjectName', $ProjectName) } + Write-Verbose -Message "Data ==== $($Data | Out-String)" if (-not $Data.ContainsKey('Tenant')) { if (-not [System.String]::IsNullOrEmpty($Data.Principal)) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 5f2d308de4..602bb22ae2 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -514,7 +514,8 @@ function Get-M365DSCTenantNameFromParameterSet [System.Collections.HashTable] $ParameterSet ) - + $VerbosePreference = 'Continue' + Write-Verbose "ParameterSet ==== $($ParameterSet | Out-String)" if ($ParameterSet.TenantId) { return $ParameterSet.TenantId @@ -898,35 +899,35 @@ function Test-M365DSCParameterState $EventMessage = [System.Text.StringBuilder]::New() $EventMessage.Append("`r`n") | Out-Null $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues + Write-Verbose -Message "Found Tenant Name: $TenantName" $EventMessage.Append(" `r`n") | Out-Null - $EventMessage.Append(" `r`n") | Out-Null + + $driftedData = [System.Collections.Generic.Dictionary[[String], [String]]]::new() + $driftedData.Add('Tenant', $TenantName) + $driftedData.Add('Resource', $source.Split('_')[1]) + $driftedData.Add('Event', 'DriftedParameter') + + # If custom App Insights is specified, allow for the current and desired values to be captured; + # ISSUE #1222 + if ($null -ne $env:M365DSCTelemetryInstrumentationKey -and ` + $env:M365DSCTelemetryInstrumentationKey -ne 'bc5aa204-0b1e-4499-a955-d6a639bdb4fa' -and ` + $env:M365DSCTelemetryInstrumentationKey -ne 'e670af5d-fd30-4407-a796-8ad30491ea7a') + { + $driftedData.Add('CurrentValues', $CurrentValues) + $driftedData.Add('DesiredValues', $DesiredValues) + } + #endregion + $telemetryDriftedParameters = '' foreach ($key in $DriftedParameters.Keys) { Write-Verbose -Message "Detected Drifted Parameter [$Source]$key" - - #region Telemetry - $driftedData = [System.Collections.Generic.Dictionary[[String], [String]]]::new() - $driftedData.Add('Event', 'DriftedParameter') - $driftedData.Add('Parameter', "[$Source]$key") - - # If custom App Insights is specified, allow for the current and desired values to be captured; - # ISSUE #1222 - if ($null -ne $env:M365DSCTelemetryInstrumentationKey -and ` - $env:M365DSCTelemetryInstrumentationKey -ne 'bc5aa204-0b1e-4499-a955-d6a639bdb4fa' -and ` - $env:M365DSCTelemetryInstrumentationKey -ne 'e670af5d-fd30-4407-a796-8ad30491ea7a') - { - $driftedData.Add('CurrentValue', [string]($CurrentValues[$key])) - $driftedData.Add('DesiredValue', [string]($DesiredValues[$key])) - } - $TenantName = Get-M365DSCTenantNameFromParameterSet -ParameterSet $DesiredValues - $driftedData.Add('Tenant', $TenantName) - $driftedData.Add('Resource', $source.Split('_')[1]) - Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData - #endregion + $telemetryDriftedParameters += $key + "`r`n" $EventMessage.Append(" " + $DriftedParameters.$key + "`r`n") | Out-Null } + $driftedData.Add('Parameters', $telemetryDriftedParameters) + Add-M365DSCTelemetryEvent -Type 'DriftInfo' -Data $driftedData $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null From f1d585ef930b486d037478110722356757bc907f Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Thu, 15 Feb 2024 06:56:03 -0500 Subject: [PATCH 152/171] Fixes Verbose --- Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 | 2 -- Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 -- 2 files changed, 4 deletions(-) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 47a4fdcedb..040a59f077 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -53,7 +53,6 @@ function Add-M365DSCTelemetryEvent [System.Collections.Generic.Dictionary[[System.String], [System.Double]]] $Metrics ) - $verbosepreference = 'continue' $TelemetryEnabled = [System.Environment]::GetEnvironmentVariable('M365DSCTelemetryEnabled', ` [System.EnvironmentVariableTarget]::Machine) @@ -71,7 +70,6 @@ function Add-M365DSCTelemetryEvent $Data.Add('ProjectName', $ProjectName) } - Write-Verbose -Message "Data ==== $($Data | Out-String)" if (-not $Data.ContainsKey('Tenant')) { if (-not [System.String]::IsNullOrEmpty($Data.Principal)) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 602bb22ae2..1792d9d6d4 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -514,8 +514,6 @@ function Get-M365DSCTenantNameFromParameterSet [System.Collections.HashTable] $ParameterSet ) - $VerbosePreference = 'Continue' - Write-Verbose "ParameterSet ==== $($ParameterSet | Out-String)" if ($ParameterSet.TenantId) { return $ParameterSet.TenantId From cc38c28ccf298c073750dc5a4f4130d8faf8c310 Mon Sep 17 00:00:00 2001 From: Andrew Hodgson Date: Mon, 5 Feb 2024 15:57:58 +0000 Subject: [PATCH 153/171] Expose the Description field in the MSFT_AADApplication DSC resource Update unit tests Update Update Get-Resource test --- .../MSFT_AADApplication/MSFT_AADApplication.psm1 | 14 ++++++++++++++ .../MSFT_AADApplication.schema.mof | 1 + .../Examples/Resources/AADApplication/1-Create.ps1 | 1 + .../Examples/Resources/AADApplication/2-Update.ps1 | 1 + .../M365DSCIntegration.AAD.Create.Tests.ps1 | 1 + .../Microsoft365DSC.AADApplication.Tests.ps1 | 11 ++++++++++- docs/docs/resources/azure-ad/AADApplication.md | 1 + 7 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index 418aefd556..a6239345d7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -20,6 +20,10 @@ function Get-TargetResource [System.Boolean] $AvailableToOtherTenants, + [Parameter()] + [System.String] + $Description, + [Parameter()] [System.String] $GroupMembershipClaims, @@ -189,6 +193,7 @@ function Get-TargetResource $result = @{ DisplayName = $AADApp.DisplayName AvailableToOtherTenants = $AvailableToOtherTenantsValue + Description = $AADApp.Description GroupMembershipClaims = $AADApp.GroupMembershipClaims Homepage = $AADApp.web.HomepageUrl IdentifierUris = $AADApp.IdentifierUris @@ -253,6 +258,10 @@ function Set-TargetResource [System.Boolean] $AvailableToOtherTenants, + [Parameter()] + [System.String] + $Description, + [Parameter()] [System.String] $GroupMembershipClaims, @@ -682,6 +691,10 @@ function Test-TargetResource [System.Boolean] $AvailableToOtherTenants, + [Parameter()] + [System.String] + $Description, + [Parameter()] [System.String] $GroupMembershipClaims, @@ -884,6 +897,7 @@ function Export-TargetResource TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint ApplicationSecret = $ApplicationSecret + Description = $AADApp.Description DisplayName = $AADApp.DisplayName ObjectID = $AADApp.Id Credential = $Credential diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof index d0cd6efbcf..9bfbfdb9e0 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.schema.mof @@ -14,6 +14,7 @@ class MSFT_AADApplication : OMI_BaseResource [Write, Description("ObjectID of the app.")] String ObjectId; [Write, Description("AppId for the app.")] String AppId; [Write, Description("Indicates whether this application is available in other tenants.")] Boolean AvailableToOtherTenants; + [Write, Description("A free text field to provide a description of the application object to end users. The maximum allowed size is 1024 characters.")] String Description; [Write, Description("A bitmask that configures the groups claim issued in a user or OAuth 2.0 access token that the application expects.")] String GroupMembershipClaims; [Write, Description("The URL to the application's homepage.")] String Homepage; [Write, Description("User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain.")] string IdentifierUris[]; diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADApplication/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADApplication/1-Create.ps1 index c57e9ba949..50de632034 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADApplication/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADApplication/1-Create.ps1 @@ -19,6 +19,7 @@ Configuration Example { DisplayName = "AppDisplayName" AvailableToOtherTenants = $false + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" diff --git a/Modules/Microsoft365DSC/Examples/Resources/AADApplication/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/AADApplication/2-Update.ps1 index fc9c39407e..b61f02d26f 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/AADApplication/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/AADApplication/2-Update.ps1 @@ -19,6 +19,7 @@ Configuration Example { DisplayName = "AppDisplayName" AvailableToOtherTenants = $true # Updated Property + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 4875dab41a..ef9731b921 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -32,6 +32,7 @@ { DisplayName = "AppDisplayName" AvailableToOtherTenants = $false + Description = 'Test Description' GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index 07b9c9254c..c9f8a45804 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -1,5 +1,5 @@ [CmdletBinding()] -param( + param( ) $M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` -ChildPath '..\..\Unit' ` @@ -73,6 +73,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ DisplayName = 'App1' AvailableToOtherTenants = $false + Description = 'App description' GroupMembershipClaims = '0' Homepage = 'https://app.contoso.com' IdentifierUris = 'https://app.contoso.com' @@ -108,6 +109,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { ObjectId = '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' DisplayName = 'App1' AvailableToOtherTenants = $false + Description = 'App description' GroupMembershipClaims = '0' Homepage = 'https://app.contoso.com' IdentifierUris = 'https://app.contoso.com' @@ -124,6 +126,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' $AADApp | Add-Member -MemberType NoteProperty -Name AvailableToOtherTenants -Value $false + $AADApp | Add-Member -MemberType NoteProperty -Name Description -Value 'App description' $AADApp | Add-Member -MemberType NoteProperty -Name GroupMembershipClaims -Value 0 $AADApp | Add-Member -MemberType NoteProperty -Name Homepage -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' @@ -156,6 +159,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ DisplayName = 'App1' AvailableToOtherTenants = $false + Description = 'App description' GroupMembershipClaims = '0' Homepage = 'https://app.contoso.com' IdentifierUris = 'https://app.contoso.com' @@ -171,6 +175,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp = New-Object PSCustomObject $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' + $AADApp | Add-Member -MemberType NoteProperty -Name Description -Value 'App description' $AADApp | Add-Member -MemberType NoteProperty -Name GroupMembershipClaims -Value 0 $AADApp | Add-Member -MemberType NoteProperty -Name SignInAudience -Value 'AzureADMyOrg' $AADApp | Add-Member -MemberType NoteProperty -Name Web -Value @{ @@ -203,6 +208,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ DisplayName = 'App1' AvailableToOtherTenants = $false + Description = 'App description' GroupMembershipClaims = '0' Homepage = 'https://app1.contoso.com' #drift IdentifierUris = 'https://app.contoso.com' @@ -219,6 +225,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' $AADApp | Add-Member -MemberType NoteProperty -Name AvailableToOtherTenants -Value $false + $AADApp | Add-Member -MemberType NoteProperty -Name Description -Value 'App description' $AADApp | Add-Member -MemberType NoteProperty -Name GroupMembershipClaims -Value 0 $AADApp | Add-Member -MemberType NoteProperty -Name Homepage -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' @@ -251,6 +258,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ DisplayName = 'App1' AvailableToOtherTenants = $false + Description = 'App description' GroupMembershipClaims = '0' IdentifierUris = 'https://app.contoso.com' KnownClientApplications = '' @@ -313,6 +321,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AADApp | Add-Member -MemberType NoteProperty -Name DisplayName -Value 'App1' $AADApp | Add-Member -MemberType NoteProperty -Name Id -Value '5dcb2237-c61b-4258-9c85-eae2aaeba9d6' $AADApp | Add-Member -MemberType NoteProperty -Name AvailableToOtherTenants -Value $false + $AADApp | Add-Member -MemberType NoteProperty -Name Description -Value 'App description' $AADApp | Add-Member -MemberType NoteProperty -Name GroupMembershipClaims -Value 0 $AADApp | Add-Member -MemberType NoteProperty -Name Homepage -Value 'https://app.contoso.com' $AADApp | Add-Member -MemberType NoteProperty -Name IdentifierUris -Value 'https://app.contoso.com' diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 905304b5cc..28262e304e 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -8,6 +8,7 @@ | **ObjectId** | Write | String | ObjectID of the app. | | | **AppId** | Write | String | AppId for the app. | | | **AvailableToOtherTenants** | Write | Boolean | Indicates whether this application is available in other tenants. | | +| **Description** | Write | String | A free text field to provide a description of the application object to end users. The maximum allowed size is 1024 characters. | | | **GroupMembershipClaims** | Write | String | A bitmask that configures the groups claim issued in a user or OAuth 2.0 access token that the application expects. | | | **Homepage** | Write | String | The URL to the application's homepage. | | | **IdentifierUris** | Write | StringArray[] | User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain. | | From cd2ca37a4958d3524cedaedf5fdfb7510e2a68d3 Mon Sep 17 00:00:00 2001 From: Andrew Hodgson Date: Fri, 16 Feb 2024 16:40:21 +0000 Subject: [PATCH 154/171] Update per feedback --- .../Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 | 2 +- .../Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 | 2 +- docs/docs/resources/azure-ad/AADApplication.md | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index ef9731b921..0fa22c30a2 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -32,7 +32,7 @@ { DisplayName = "AppDisplayName" AvailableToOtherTenants = $false - Description = 'Test Description' + Description = 'Test Description' GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 index c9f8a45804..60dc43ed27 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.AADApplication.Tests.ps1 @@ -1,5 +1,5 @@ [CmdletBinding()] - param( +param( ) $M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` -ChildPath '..\..\Unit' ` diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 28262e304e..905304b5cc 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -8,7 +8,6 @@ | **ObjectId** | Write | String | ObjectID of the app. | | | **AppId** | Write | String | AppId for the app. | | | **AvailableToOtherTenants** | Write | Boolean | Indicates whether this application is available in other tenants. | | -| **Description** | Write | String | A free text field to provide a description of the application object to end users. The maximum allowed size is 1024 characters. | | | **GroupMembershipClaims** | Write | String | A bitmask that configures the groups claim issued in a user or OAuth 2.0 access token that the application expects. | | | **Homepage** | Write | String | The URL to the application's homepage. | | | **IdentifierUris** | Write | StringArray[] | User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain. | | From a7aeacd4169176101bc54bc85751934b00ad281f Mon Sep 17 00:00:00 2001 From: Andrew Hodgson Date: Fri, 16 Feb 2024 16:50:03 +0000 Subject: [PATCH 155/171] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 880bdd44b5..7deda1858b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change log for Microsoft365DSC +# UNRELEASED +* AADApplication + * Expose the description field in the resource. + # 1.24.214.2 * AADConditionalAccessPolicy From 3ce796a38be548e64bbfb936ee00464d9e68ab16 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Mon, 19 Feb 2024 08:37:27 -0500 Subject: [PATCH 156/171] Release 1.24.214.3 --- CHANGELOG.md | 29 +++ .../MSFT_AADAuthenticationMethodPolicy.psm1 | 187 +++++++++--------- ...thenticationMethodPolicyAuthenticator.psm1 | 2 +- ...FT_AADAuthenticationMethodPolicyEmail.psm1 | 2 +- ...FT_AADAuthenticationMethodPolicyFido2.psm1 | 2 +- ...MSFT_AADAuthenticationMethodPolicySms.psm1 | 2 +- ...AADAuthenticationMethodPolicySoftware.psm1 | 2 +- ...ADAuthenticationMethodPolicyTemporary.psm1 | 2 +- ...FT_AADAuthenticationMethodPolicyVoice.psm1 | 2 +- ...SFT_AADAuthenticationMethodPolicyX509.psm1 | 2 +- .../MSFT_IntuneAppConfigurationPolicy.psm1 | 2 +- ...neDeviceEnrollmentStatusPageWindows10.psm1 | 7 +- ...topilotDeploymentProfileAzureADJoined.psm1 | 6 +- .../Dependencies/Manifest.psd1 | 34 ++-- .../Modules/M365DSCTelemetryEngine.psm1 | 8 + .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 80 +++++--- 16 files changed, 223 insertions(+), 146 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 880bdd44b5..a965c0ed7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Change log for Microsoft365DSC +# 1.24.214.3 + +* AADAuthenticationMethodPolicy + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyAuthenticator + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyEmail + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyFido2 + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicySms + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicySoftware + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyTemporary + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyVoice + * Fixed an error where the Export method would loop through the response header. +* AADAuthenticationMethodPolicyX509 + * Fixed an error where the Export method would loop through the response header. +* IntuneAppConfigurationPolicy + * Fixed an error in the export on the Settings property. +* IntuneDeviceEnrollmentStatusPageWindows10 + * Fixed an error where the Export method would loop through the response header. +* IntuneWindowsAutopilotDeploymentProfileAzureADJoined + * Fixed an error where the Export method would loop through the response header. +* DEPENDENCIES + * Updated Microsoft.Graph to version 2.14.0. + # 1.24.214.2 * AADConditionalAccessPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 index bc133df731..ad70aeaa6c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicy/MSFT_AADAuthenticationMethodPolicy.psm1 @@ -555,7 +555,7 @@ function Export-TargetResource { #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicy ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.DisplayName} #endregion $i = 1 @@ -574,111 +574,112 @@ function Export-TargetResource if (-not [String]::IsNullOrEmpty($config.displayName)) { $displayedKey = $config.displayName - } - Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline - $params = @{ - Id = $config.Id - DisplayName = $config.DisplayName - Ensure = 'Present' - Credential = $Credential - ApplicationId = $ApplicationId - TenantId = $TenantId - ApplicationSecret = $ApplicationSecret - CertificateThumbprint = $CertificateThumbprint - Managedidentity = $ManagedIdentity.IsPresent - } - $Results = Get-TargetResource @Params - $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` - -Results $Results - if ($null -ne $Results.RegistrationEnforcement) - { - $complexMapping = @( - @{ - Name = 'RegistrationEnforcement' - CimInstanceName = 'MicrosoftGraphRegistrationEnforcement' - IsRequired = $False - } - @{ - Name = 'AuthenticationMethodsRegistrationCampaign' - CimInstanceName = 'MicrosoftGraphAuthenticationMethodsRegistrationCampaign' - IsRequired = $False - } - @{ - Name = 'ExcludeTargets' - CimInstanceName = 'MicrosoftGraphExcludeTarget' - IsRequired = $False - } - @{ - Name = 'IncludeTargets' - CimInstanceName = 'MicrosoftGraphAuthenticationMethodsRegistrationCampaignIncludeTarget' - IsRequired = $False - } - ) - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` - -ComplexObject $Results.RegistrationEnforcement ` - -CIMInstanceName 'MicrosoftGraphregistrationEnforcement' ` - -ComplexTypeMapping $complexMapping + Write-Host " |---[$i/$($getValue.Count)] $displayedKey" -NoNewline + $params = @{ + Id = $config.Id + DisplayName = $config.DisplayName + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + ApplicationSecret = $ApplicationSecret + CertificateThumbprint = $CertificateThumbprint + Managedidentity = $ManagedIdentity.IsPresent + } - if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + if ($null -ne $Results.RegistrationEnforcement) { - $Results.RegistrationEnforcement = $complexTypeStringResult + $complexMapping = @( + @{ + Name = 'RegistrationEnforcement' + CimInstanceName = 'MicrosoftGraphRegistrationEnforcement' + IsRequired = $False + } + @{ + Name = 'AuthenticationMethodsRegistrationCampaign' + CimInstanceName = 'MicrosoftGraphAuthenticationMethodsRegistrationCampaign' + IsRequired = $False + } + @{ + Name = 'ExcludeTargets' + CimInstanceName = 'MicrosoftGraphExcludeTarget' + IsRequired = $False + } + @{ + Name = 'IncludeTargets' + CimInstanceName = 'MicrosoftGraphAuthenticationMethodsRegistrationCampaignIncludeTarget' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.RegistrationEnforcement ` + -CIMInstanceName 'MicrosoftGraphregistrationEnforcement' ` + -ComplexTypeMapping $complexMapping + + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.RegistrationEnforcement = $complexTypeStringResult + } + else + { + $Results.Remove('RegistrationEnforcement') | Out-Null + } } - else + if ($null -ne $Results.SystemCredentialPreferences) { - $Results.Remove('RegistrationEnforcement') | Out-Null - } - } - if ($null -ne $Results.SystemCredentialPreferences) - { - $complexMapping = @( - @{ - Name = 'SystemCredentialPreferences' - CimInstanceName = 'MicrosoftGraphSystemCredentialPreferences' - IsRequired = $False + $complexMapping = @( + @{ + Name = 'SystemCredentialPreferences' + CimInstanceName = 'MicrosoftGraphSystemCredentialPreferences' + IsRequired = $False + } + @{ + Name = 'ExcludeTargets' + CimInstanceName = 'AADAuthenticationMethodPolicyExcludeTarget' + IsRequired = $False + } + @{ + Name = 'IncludeTargets' + CimInstanceName = 'AADAuthenticationMethodPolicyIncludeTarget' + IsRequired = $False + } + ) + $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` + -ComplexObject $Results.SystemCredentialPreferences ` + -CIMInstanceName 'MicrosoftGraphsystemCredentialPreferences' ` + -ComplexTypeMapping $complexMapping + + if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + { + $Results.SystemCredentialPreferences = $complexTypeStringResult } - @{ - Name = 'ExcludeTargets' - CimInstanceName = 'AADAuthenticationMethodPolicyExcludeTarget' - IsRequired = $False + else + { + $Results.Remove('SystemCredentialPreferences') | Out-Null } - @{ - Name = 'IncludeTargets' - CimInstanceName = 'AADAuthenticationMethodPolicyIncludeTarget' - IsRequired = $False - } - ) - $complexTypeStringResult = Get-M365DSCDRGComplexTypeToString ` - -ComplexObject $Results.SystemCredentialPreferences ` - -CIMInstanceName 'MicrosoftGraphsystemCredentialPreferences' ` - -ComplexTypeMapping $complexMapping + } - if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult)) + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + if ($Results.RegistrationEnforcement) { - $Results.SystemCredentialPreferences = $complexTypeStringResult + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "RegistrationEnforcement" -isCIMArray:$False } - else + if ($Results.SystemCredentialPreferences) { - $Results.Remove('SystemCredentialPreferences') | Out-Null + $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "SystemCredentialPreferences" -isCIMArray:$False } + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName } - - $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` - -ConnectionMode $ConnectionMode ` - -ModulePath $PSScriptRoot ` - -Results $Results ` - -Credential $Credential - if ($Results.RegistrationEnforcement) - { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "RegistrationEnforcement" -isCIMArray:$False - } - if ($Results.SystemCredentialPreferences) - { - $currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName "SystemCredentialPreferences" -isCIMArray:$False - } - $dscContent += $currentDSCBlock - Save-M365DSCPartialExport -Content $currentDSCBlock ` - -FileName $Global:PartialExportFileName $i++ Write-Host $Global:M365DSCEmojiGreenCheckMark } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyAuthenticator/MSFT_AADAuthenticationMethodPolicyAuthenticator.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyAuthenticator/MSFT_AADAuthenticationMethodPolicyAuthenticator.psm1 index dfd66443d9..dc55e471df 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyAuthenticator/MSFT_AADAuthenticationMethodPolicyAuthenticator.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyAuthenticator/MSFT_AADAuthenticationMethodPolicyAuthenticator.psm1 @@ -715,7 +715,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId MicrosoftAuthenticator ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyEmail/MSFT_AADAuthenticationMethodPolicyEmail.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyEmail/MSFT_AADAuthenticationMethodPolicyEmail.psm1 index d003bcb1b2..1ea4e8d70c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyEmail/MSFT_AADAuthenticationMethodPolicyEmail.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyEmail/MSFT_AADAuthenticationMethodPolicyEmail.psm1 @@ -495,7 +495,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId Email ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyFido2/MSFT_AADAuthenticationMethodPolicyFido2.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyFido2/MSFT_AADAuthenticationMethodPolicyFido2.psm1 index f185f8d8cd..5e1bd2fce9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyFido2/MSFT_AADAuthenticationMethodPolicyFido2.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyFido2/MSFT_AADAuthenticationMethodPolicyFido2.psm1 @@ -523,7 +523,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId Fido2 ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySms/MSFT_AADAuthenticationMethodPolicySms.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySms/MSFT_AADAuthenticationMethodPolicySms.psm1 index 6468ccd7ba..8ac4fd6b8e 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySms/MSFT_AADAuthenticationMethodPolicySms.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySms/MSFT_AADAuthenticationMethodPolicySms.psm1 @@ -471,7 +471,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId sms ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySoftware/MSFT_AADAuthenticationMethodPolicySoftware.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySoftware/MSFT_AADAuthenticationMethodPolicySoftware.psm1 index b455da368a..0a2f0a50f5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySoftware/MSFT_AADAuthenticationMethodPolicySoftware.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicySoftware/MSFT_AADAuthenticationMethodPolicySoftware.psm1 @@ -471,7 +471,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId SoftwareOath ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyTemporary/MSFT_AADAuthenticationMethodPolicyTemporary.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyTemporary/MSFT_AADAuthenticationMethodPolicyTemporary.psm1 index fd509d30a2..2fd4718e04 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyTemporary/MSFT_AADAuthenticationMethodPolicyTemporary.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyTemporary/MSFT_AADAuthenticationMethodPolicyTemporary.psm1 @@ -540,7 +540,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId TemporaryAccessPass ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyVoice/MSFT_AADAuthenticationMethodPolicyVoice.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyVoice/MSFT_AADAuthenticationMethodPolicyVoice.psm1 index 63a37ba8b8..e816c4dfc6 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyVoice/MSFT_AADAuthenticationMethodPolicyVoice.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyVoice/MSFT_AADAuthenticationMethodPolicyVoice.psm1 @@ -484,7 +484,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId Voice ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyX509/MSFT_AADAuthenticationMethodPolicyX509.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyX509/MSFT_AADAuthenticationMethodPolicyX509.psm1 index b6cb728bb6..b79f23dec4 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyX509/MSFT_AADAuthenticationMethodPolicyX509.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADAuthenticationMethodPolicyX509/MSFT_AADAuthenticationMethodPolicyX509.psm1 @@ -547,7 +547,7 @@ function Export-TargetResource #region resource generator code [array]$getValue = Get-MgBetaPolicyAuthenticationMethodPolicyAuthenticationMethodConfiguration ` -AuthenticationMethodConfigurationId X509Certificate ` - -ErrorAction Stop + -ErrorAction Stop | Where-Object -FilterScript {$null -ne $_.Id} #endregion $i = 1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 index d8575c1170..eab7b43d76 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneAppConfigurationPolicy/MSFT_IntuneAppConfigurationPolicy.psm1 @@ -587,7 +587,7 @@ function Get-M365DSCIntuneAppConfigurationPolicyCustomSettingsAsString [OutputType([System.String])] param( [Parameter(Mandatory = $true)] - [System.Collections.ArrayList] + [System.Object[]] $Settings ) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentStatusPageWindows10/MSFT_IntuneDeviceEnrollmentStatusPageWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentStatusPageWindows10/MSFT_IntuneDeviceEnrollmentStatusPageWindows10.psm1 index c737bd8164..2b1043cca7 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentStatusPageWindows10/MSFT_IntuneDeviceEnrollmentStatusPageWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceEnrollmentStatusPageWindows10/MSFT_IntuneDeviceEnrollmentStatusPageWindows10.psm1 @@ -126,7 +126,8 @@ function Get-TargetResource $getValue = $null #region resource generator code - $getValue = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $Id -ErrorAction SilentlyContinue + $getValue = Get-MgBetaDeviceManagementDeviceEnrollmentConfiguration -DeviceEnrollmentConfigurationId $Id -ErrorAction SilentlyContinue ` + | Where-Object -FilterScript {$null -ne $_.DisplayName} if ($null -eq $getValue) { @@ -139,7 +140,7 @@ function Get-TargetResource -ErrorAction SilentlyContinue | Where-Object ` -FilterScript { ` $_.AdditionalProperties.'@odata.type' -eq '#microsoft.graph.windows10EnrollmentCompletionPageConfiguration' ` - } + } | Where-Object -FilterScript {$null -ne $_.DisplayName} } } #endregion @@ -149,7 +150,7 @@ function Get-TargetResource return $nullResult } - if($getValue -is [Array]) + if($getValue -is [Array] -and $getValue.Length -gt 1) { Throw "The DisplayName {$DisplayName} returned multiple policies, make sure DisplayName is unique." } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined.psm1 index f6a4bad9e8..c9ee94540c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined/MSFT_IntuneWindowsAutopilotDeploymentProfileAzureADJoined.psm1 @@ -107,7 +107,8 @@ function Get-TargetResource $getValue = $null #region resource generator code - $getValue = Get-MgBetaDeviceManagementWindowsAutopilotDeploymentProfile -WindowsAutopilotDeploymentProfileId $Id -ErrorAction SilentlyContinue + $getValue = Get-MgBetaDeviceManagementWindowsAutopilotDeploymentProfile -WindowsAutopilotDeploymentProfileId $Id -ErrorAction SilentlyContinue ` + | Where-Object -FilterScript {$null -ne $_.DisplayName} if ($null -eq $getValue) { @@ -117,7 +118,8 @@ function Get-TargetResource { $getValue = Get-MgBetaDeviceManagementWindowsAutopilotDeploymentProfile ` -Filter "DisplayName eq '$DisplayName'" ` - -ErrorAction SilentlyContinue + -ErrorAction SilentlyContinue ` + | Where-Object -FilterScript {$null -ne $_.DisplayName} } } #endregion diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 437b3cc54f..b0dd1f6587 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -10,71 +10,71 @@ }, @{ ModuleName = 'Microsoft.Graph.Applications' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Authentication' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Enrollment' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.Governance' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Reports' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement.Administration' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Beta.DirectoryObjects' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Groups' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Planner' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Users' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.Graph.Users.Actions' - RequiredVersion = '2.13.1' + RequiredVersion = '2.14.0' }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index 040a59f077..f7f155f0ae 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -264,6 +264,14 @@ function Add-M365DSCTelemetryEvent $M365DSCTelemetryEventId = (New-GUID).ToString() $Data.Add('M365DSCTelemetryEventId', $M365DSCTelemetryEventId) + if ([System.String]::IsNullOrEMpty($Type)) + { + if ((-not [System.String]::IsNullOrEmpty($Data.Method) -and $Data.Method -eq 'Export-TargetResource') -or $Global:M365DSCExportInProgress) + { + $Type = 'Export' + } + } + $TelemetryClient.TrackEvent($Type, $Data, $Metrics) } catch diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 1792d9d6d4..79bbb1650c 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -577,7 +577,12 @@ function Test-M365DSCParameterState #endregion $returnValue = $true - $DriftedParameters = @{ } + $DriftedParameters = @{} + $DriftObject = @{ + DriftInfo = @{} + CurrentValues = @{} + DesiredValues = @{} + } if ($null -ne $IncludedDrifts -and $IncludedDrifts.Keys.Count -gt 0) { $DriftedParameters = $IncludedDrifts @@ -643,6 +648,7 @@ function Test-M365DSCParameterState 'values, but it was either not present or ' + ` 'was null. This has caused the test method ' + ` 'to return false.') + $DriftObject.DriftInfo.Add($fieldName, '') $DriftedParameters.Add($fieldName, '') $returnValue = $false } @@ -679,6 +685,11 @@ function Test-M365DSCParameterState if (-not $DriftedParameters.ContainsKey($fieldName)) { + $DriftObject.DriftInfo.Add($fieldName, @{ + PropertyName = $item.PropertyName + CurrentValue = $item.CurrentValue + DesiredValue = $item.DesiredValue + }) $DriftedParameters.Add($fieldName, $EventValue) } } @@ -702,6 +713,10 @@ function Test-M365DSCParameterState $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -727,6 +742,10 @@ function Test-M365DSCParameterState "'$($DesiredValues.$fieldName)'") $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -747,6 +766,10 @@ function Test-M365DSCParameterState "'$($DesiredValues.$fieldName)'") $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -767,6 +790,10 @@ function Test-M365DSCParameterState "'$($DesiredValues.$fieldName)'") $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -783,6 +810,10 @@ function Test-M365DSCParameterState "'$($DesiredValues.$fieldName)'") $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -803,6 +834,10 @@ function Test-M365DSCParameterState "'$($DesiredValues.$fieldName)'") $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -858,6 +893,11 @@ function Test-M365DSCParameterState if (-not $DriftedParameters.ContainsKey($fieldName)) { $DriftedParameters.Add($fieldName, $EventValue) + $DriftObject.DriftInfo.Add($fieldName, @{ + PropertyName = $item.PropertyName + CurrentValue = $item.CurrentValue + DesiredValue = $item.DesiredValue + }) } } $returnValue = $false @@ -872,6 +912,11 @@ function Test-M365DSCParameterState 'Test-M365DSCParameterState cmdlet') $EventValue = "$($CurrentValues.$fieldName)" $EventValue += "$($DesiredValues.$fieldName)" + + $DriftObject.DriftInfo.Add($fieldName, @{ + CurrentValue = $CurrentValues.$fieldName + DesiredValue = $DesiredValues.$fieldName + }) $DriftedParameters.Add($fieldName, $EventValue) $returnValue = $false } @@ -903,7 +948,9 @@ function Test-M365DSCParameterState $driftedData = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $driftedData.Add('Tenant', $TenantName) + $DriftObject.Add('Tenant', $TenantName) $driftedData.Add('Resource', $source.Split('_')[1]) + $DriftObject.Add('Resource', $source.Split('_')[1]) $driftedData.Add('Event', 'DriftedParameter') # If custom App Insights is specified, allow for the current and desired values to be captured; @@ -937,6 +984,7 @@ function Test-M365DSCParameterState $Value = "`$null" } $EventMessage.Append(" $Value`r`n") | Out-Null + $DriftObject.DesiredValues.Add($key, $value) } $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append(" `r`n") | Out-Null @@ -948,10 +996,12 @@ function Test-M365DSCParameterState $Value = "`$null" } $EventMessage.Append(" $Value`r`n") | Out-Null + $DriftObject.CurrentValues.Add($key, $value) } $EventMessage.Append(" `r`n") | Out-Null $EventMessage.Append('') | Out-Null + $Global:CCMCurrentDriftInfo = $DriftObject Add-M365DSCEvent -Message $EventMessage.ToString() -EventType 'Drift' -EntryType 'Warning' ` -EventID 1 -Source $Source } @@ -1254,9 +1304,9 @@ function Export-M365DSCConfiguration $data.Add('Path', [System.String]::IsNullOrEmpty($Path)) $data.Add('FileName', $null -ne [System.String]::IsNullOrEmpty($FileName)) - $data.Add('Components', $null -ne $Components) - $data.Add('Workloads', $null -ne $Workloads) - $data.Add('MaxProcesses', $null -ne $MaxProcesses) + $data.Add('Components', $Components) + $data.Add('Workloads', $Workloads) + $data.Add('MaxProcesses', $MaxProcesses) #endregion if ($null -eq $MaxProcesses) @@ -1275,20 +1325,10 @@ function Export-M365DSCConfiguration Write-Verbose -Message 'No existing connections to Microsoft Graph' } - if (-not [System.String]::IsNullOrEmpty($TenantId) -and -not $data.ContainsKey('Tenant')) - { - $data.Add('Tenant', $TenantId) - } - else - { - if ($Credential -and -not $data.ContainsKey('Tenant')) - { - $tenant = $Credential.UserName.Split('@')[1] - $data.Add('Tenant', $tenant) - } - } + $Tenant = Get-M365DSCTenantNameFromParameterSet -ParameterSet $PSBoundParameters + $data.Add('Tenant', $Tenant) - Add-M365DSCTelemetryEvent -Type 'Export' -Data $data + Add-M365DSCTelemetryEvent -Type 'ExportInitiated' -Data $data if ($null -ne $Workloads) { Write-Output -InputObject "Exporting Microsoft 365 configuration for Workloads: $($Workloads -join ', ')" @@ -1666,7 +1706,7 @@ function New-M365DSCConnection [System.Boolean] $SkipModuleReload = $false ) - + $Global:MaximumFunctionCount = 32767 if ($Workload -eq 'MicrosoftTeams') { try @@ -4548,10 +4588,6 @@ function Sync-M365DSCParameter { $Parameters } - else - { - $global:ALBoundParameters = $Parameters - } } Export-ModuleMember -Function @( From 60b617bdea895e22982c2c0d0eb58d437b2584c9 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 07:12:24 -0500 Subject: [PATCH 157/171] Release candidate --- .../Dependencies/Manifest.psd1 | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index b0dd1f6587..7183bc25aa 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -10,71 +10,71 @@ }, @{ ModuleName = 'Microsoft.Graph.Applications' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Authentication' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Devices.CorporateManagement' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Administration' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DeviceManagement.Enrollment' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.DirectoryManagement' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.Governance' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Identity.SignIns' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Reports' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.Teams' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.DeviceManagement.Administration' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Beta.DirectoryObjects' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Groups' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Planner' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Users' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.Graph.Users.Actions' - RequiredVersion = '2.14.0' + RequiredVersion = '2.14.1' }, @{ ModuleName = 'Microsoft.PowerApps.Administration.PowerShell' From 3fb09778f3c35523e52bfba52b1802a10e9ebe60 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 07:13:01 -0500 Subject: [PATCH 158/171] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a965c0ed7d..dc9b84b1b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ * IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Fixed an error where the Export method would loop through the response header. * DEPENDENCIES - * Updated Microsoft.Graph to version 2.14.0. + * Updated Microsoft.Graph to version 2.14.1. # 1.24.214.2 From d1d9d1d054cce041f5ed4a137a65c0fde14963ff Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 08:07:05 -0500 Subject: [PATCH 159/171] Update MSFT_SCDLPComplianceRule.psm1 --- .../MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 index d2f4d0c29f..8e2cf780e5 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCDLPComplianceRule/MSFT_SCDLPComplianceRule.psm1 @@ -406,8 +406,8 @@ function Get-TargetResource GenerateIncidentReport = $PolicyRule.GenerateIncidentReport IncidentReportContent = $ArrayIncidentReportContent NotifyAllowOverride = $NotifyAllowOverrideValue - NotifyEmailCustomText = $PolicyRule.NotifyEmailCustomText - NotifyPolicyTipCustomText = $PolicyRule.NotifyPolicyTipCustomText + NotifyEmailCustomText = [regex]::Replace($PolicyRule.NotifyEmailCustomText, $fancyDoubleQuotes, "`"") + NotifyPolicyTipCustomText = [regex]::Replace($PolicyRule.NotifyPolicyTipCustomText, $fancyDoubleQuotes, "`"") NotifyUser = $PolicyRule.NotifyUser ReportSeverityLevel = $PolicyRule.ReportSeverityLevel RuleErrorAction = $PolicyRule.RuleErrorAction From a778d65fa0e5eaedda29bf16cf210167184b9191 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 08:44:16 -0500 Subject: [PATCH 160/171] Update Microsoft365DSC.psd1 --- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 81 +++++++------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 6e3fad6c64..468761965e 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-14 +# Generated on: 2024-02-20 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.214.2' + ModuleVersion = '1.24.214.3' # Supported PSEditions # CompatiblePSEditions = @() @@ -140,61 +140,32 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* AADConditionalAccessPolicy - * Removed invalid empty string value that was added to the validate set - of two parameters. - * Updated permission reference for app-onlzy authentication. - FIXES [[#3329](https://github.com/microsoft/Microsoft365DSC/issues/3329)] - * AADRoleEligibilityScheduleRequest - * Fixed an issue where an error was thrown if no requests were found instead - of simply returning the Null object. - * AADRoleSetting - * Fix handling of DisplayName property in comparison - FIXES [#4019](https://github.com/microsoft/Microsoft365DSC/issues/4019) - * AADUser - * Fixed and issue where an user would be created even if the resrouce was set to absent. - FIXES [[#4265](https://github.com/microsoft/Microsoft365DSC/issues/4265)] - * EXOMobileDeviceMailboxPolicy - * Fixes an issue where an empty MinPasswordLength value was always passed down - to the update logic flow. + ReleaseNotes = '* AADAuthenticationMethodPolicy + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyAuthenticator + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyEmail + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyFido2 + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicySms + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicySoftware + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyTemporary + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyVoice + * Fixed an error where the Export method would loop through the response header. + * AADAuthenticationMethodPolicyX509 + * Fixed an error where the Export method would loop through the response header. * IntuneAppConfigurationPolicy - * Added parameter Id to avoid having to retrieve the same policy multiple - times - * Fixed tests in Test-TargetResource to ensure the resource reports its - correct state - FIXES [#3542](https://github.com/microsoft/Microsoft365DSC/issues/3542) - * IntuneDeviceAndAppManagementAssignmentFilter - * Fixed Test-TargetResource to ensure that resource reports its correct state - FIXES [#3959](https://github.com/microsoft/Microsoft365DSC/issues/3959) - * IntuneDeviceConfigurationNetworkBoundaryPolicyWindows10 - * Fixed Test-TargetResource by removing Id from being tested and also used - correct filter while retrieving the policy otherwise it could not be found - FIXES [#3964](https://github.com/microsoft/Microsoft365DSC/issues/3964) - * IntuneDeviceConfigurationPolicyAndroidWorkProfile - * Fix typo in variable which made it export incorrectly and report that - resource was not in correct state due to testing an incorrect value - FIXES [#3972](https://github.com/microsoft/Microsoft365DSC/issues/3972) - * IntuneSettingCatalogASRRulesPolicyWindows10 - * Fix removal of resource if Identity comes from another tenant or is not - present in blueprint - * Fix Test-TargetResource by not comparing Identity since it might be from - another tenant or not present in blueprint - FIXES [#4302](https://github.com/microsoft/Microsoft365DSC/issues/4302) - * SCDPLPCompianceRule - * Added support for multiple additional parameters. - * SPOSharingSettings - * Fixed an issue where the resource would return multiple sites. - FIXES [#2759](https://github.com/microsoft/Microsoft365DSC/issues/2759) + * Fixed an error in the export on the Settings property. + * IntuneDeviceEnrollmentStatusPageWindows10 + * Fixed an error where the Export method would loop through the response header. + * IntuneWindowsAutopilotDeploymentProfileAzureADJoined + * Fixed an error where the Export method would loop through the response header. * DEPENDENCIES - * Updated DSCParser to version 1.4.0.2. - * Updated Microsoft.Graph dependencies to version 2.13.1. - * Updated MSCloudLoginAssistant to version 1.1.13. - * MISC - * M365DSCReport - * Fix nested change detection for CIMInstances - * Fix IntuneDeviceEnrolllmentPlatformRestriction comparison in report - FIXES [#4291](https://github.com/microsoft/Microsoft365DSC/issues/4291) - * Added new QA test to check for missing description in resource schema' + * Updated Microsoft.Graph to version 2.14.1.' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false From 743f6e73c207a440fd61bdd9532900d112900d46 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 08:59:54 -0500 Subject: [PATCH 161/171] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc9b84b1b1..ab943add62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,9 @@ * Fixed an error where the Export method would loop through the response header. * IntuneWindowsAutopilotDeploymentProfileAzureADJoined * Fixed an error where the Export method would loop through the response header. +* SCDLPComplianceRule + * Fixed the NotifyEmailCustomText and NotifyPolicyTipCustomText to escape fancy + quotes. * DEPENDENCIES * Updated Microsoft.Graph to version 2.14.1. From 9218c499c22d14d6a431d54ad43fa3a160dc14b6 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Tue, 20 Feb 2024 15:35:29 -0500 Subject: [PATCH 162/171] AADConditionalAccessPolicy fixes --- CHANGELOG.md | 9 +++++ .../MSFT_AADConditionalAccessPolicy.psm1 | 24 +++++++++---- ...MSFT_AADConditionalAccessPolicy.schema.mof | 4 +-- .../MSFT_SCLabelPolicy.psm1 | 35 ------------------- .../MSFT_SCSensitivityLabel.psm1 | 8 ----- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 4 +++ 6 files changed, 33 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab943add62..48085fb817 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Change log for Microsoft365DSC +# UNRELEASED + +* AADConditionalAccessPolicy + * Fixing issue where Membership kinds no longer accepted empty values. + ROLLING BACK [#4344](https://github.com/microsoft/Microsoft365DSC/issues/4344) + FIXES [#4347](https://github.com/microsoft/Microsoft365DSC/issues/4347) + * Throws an error if role, user or group was not found in the Set method. + FIXES [#4342](https://github.com/microsoft/Microsoft365DSC/issues/4342) + # 1.24.214.3 * AADAuthenticationMethodPolicy diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 index 276bf4a184..c62d6a3aca 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.psm1 @@ -71,7 +71,7 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -85,7 +85,7 @@ function Get-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] @@ -755,7 +755,7 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -769,7 +769,7 @@ function Set-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] @@ -1014,6 +1014,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $_ } if ($null -eq $userguid) { @@ -1022,6 +1023,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1059,6 +1061,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $_ } if ($null -eq $userguid) { @@ -1067,6 +1070,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1102,6 +1106,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $_ } if ($GroupLookup.Length -gt 1) { @@ -1110,6 +1115,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } elseif ($null -eq $GroupLookup) { @@ -1118,6 +1124,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1149,6 +1156,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $_ } if ($GroupLookup.Length -gt 1) { @@ -1157,6 +1165,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } elseif ($null -eq $GroupLookup) { @@ -1165,6 +1174,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1198,6 +1208,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1231,6 +1242,7 @@ function Set-TargetResource -Source $($MyInvocation.MyCommand.Source) ` -TenantId $TenantId ` -Credential $Credential + throw $message } else { @@ -1738,7 +1750,7 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $IncludeExternalTenantsMembershipKind, [Parameter()] @@ -1752,7 +1764,7 @@ function Test-TargetResource [Parameter()] [System.String] - [ValidateSet('all', 'enumerated', 'unknownFutureValue')] + [ValidateSet('', 'all', 'enumerated', 'unknownFutureValue')] $ExcludeExternalTenantsMembershipKind, [Parameter()] diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof index 67ec7174fa..9d1203c2af 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADConditionalAccessPolicy/MSFT_AADConditionalAccessPolicy.schema.mof @@ -16,10 +16,10 @@ class MSFT_AADConditionalAccessPolicy : OMI_BaseResource [Write, Description("AAD Admin Roles in scope of the Policy.")] String IncludeRoles[]; [Write, Description("AAD Admin Roles out of scope of the Policy.")] String ExcludeRoles[]; [Write, Description("Represents the Included internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String IncludeGuestOrExternalUserTypes[]; - [Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind; + [Write, Description("Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String IncludeExternalTenantsMembershipKind; [Write, Description("Represents the Included collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String IncludeExternalTenantsMembers[]; [Write, Description("Represents the Excluded internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue."), ValueMap{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}, Values{"none","internalGuest","b2bCollaborationGuest","b2bCollaborationMember","b2bDirectConnectUser","otherExternalUser","serviceProvider","unknownFutureValue"}] String ExcludeGuestOrExternalUserTypes[]; - [Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"all","enumerated","unknownFutureValue"}, Values{"all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind; + [Write, Description("Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type."), ValueMap{"","all","enumerated","unknownFutureValue"}, Values{"","all","enumerated","unknownFutureValue"}] String ExcludeExternalTenantsMembershipKind; [Write, Description("Represents the Excluded collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting.")] String ExcludeExternalTenantsMembers[]; [Write, Description("Client Device Platforms in scope of the Policy.")] String IncludePlatforms[]; [Write, Description("Client Device Platforms out of scope of the Policy.")] String ExcludePlatforms[]; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCLabelPolicy/MSFT_SCLabelPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCLabelPolicy/MSFT_SCLabelPolicy.psm1 index d994b4f7f9..e773c24d7b 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCLabelPolicy/MSFT_SCLabelPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCLabelPolicy/MSFT_SCLabelPolicy.psm1 @@ -678,11 +678,6 @@ function Test-TargetResource $TestAdvancedSettings = Test-AdvancedSettings -DesiredProperty $AdvancedSettings -CurrentProperty $CurrentValues.AdvancedSettings if ($false -eq $TestAdvancedSettings) { - New-M365DSCLogEntry -Message 'AdvancedSettings do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } @@ -698,12 +693,6 @@ function Test-TargetResource if ($null -eq $configData -and $null -ne $CurrentValues.ModernGroupLocation ` -and $null -ne $RemoveModernGroupLocation) { - #last entry removed so trigger drift - New-M365DSCLogEntry -Message 'ModernGroupLocation do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } @@ -721,12 +710,6 @@ function Test-TargetResource if ($null -eq $configData -and $null -ne $CurrentValues.ModernGroupLocationException ` -and $null -ne $RemoveModernGroupLocationException) { - #last entry removed so trigger drift - New-M365DSCLogEntry -Message 'ModernGroupLocationException do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } @@ -742,12 +725,6 @@ function Test-TargetResource if ($null -eq $configData -and $null -ne $CurrentValues.ExchangeLocation ` -and $null -ne $RemoveExchangeLocation) { - #last entry removed so trigger drift - New-M365DSCLogEntry -Message 'ExchangeLocation do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } @@ -765,12 +742,6 @@ function Test-TargetResource if ($null -eq $configData -and $null -ne $CurrentValues.ExchangeLocationException ` -and $null -ne $RemoveExchangeLocationException) { - #last entry removed so trigger drift - New-M365DSCLogEntry -Message 'ExchangeLocationException do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } @@ -788,12 +759,6 @@ function Test-TargetResource if ($null -eq $configData -and $null -ne $CurrentValues.Labels ` -and $null -ne $RemoveLabels) { - #last entry removed so trigger drift - New-M365DSCLogEntry -Message 'Labels do not match!' ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - return $false } } diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 index d53ae1df83..92f4d76bc8 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_SCSensitivityLabel/MSFT_SCSensitivityLabel.psm1 @@ -1551,14 +1551,6 @@ function Test-LocaleSettings } } - if ($foundSettings -eq $false) - { - New-M365DSCLogEntry -Message "LocaleSettings for label $Name do not match: $($driftedSetting -join ', ')" ` - -Source $($MyInvocation.MyCommand.Source) ` - -TenantId $TenantId ` - -Credential $Credential - } - Write-Verbose -Message "Test LocaleSettings returns $foundSettings" return $foundSettings } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 79bbb1650c..0f6e64939b 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1327,6 +1327,8 @@ function Export-M365DSCConfiguration $Tenant = Get-M365DSCTenantNameFromParameterSet -ParameterSet $PSBoundParameters $data.Add('Tenant', $Tenant) + $currentExportID = (New-Guid).ToString() + $data.Add('M365DSCExportId', $currentExportID) Add-M365DSCTelemetryEvent -Type 'ExportInitiated' -Data $data if ($null -ne $Workloads) @@ -1392,6 +1394,8 @@ function Export-M365DSCConfiguration # Clear the exported resource instances' names Global variable $Global:M365DSCExportedResourceInstancesNames = $null $Global:M365DSCExportInProgress = $false + + Add-M365DSCTelemetryEvent -Type 'ExportCompleted' -Data $data } $Script:M365DSCDependenciesValidated = $false From 12f43c96a35d3633bc2a810cc7095df1cf661652 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Tue, 20 Feb 2024 20:53:04 +0000 Subject: [PATCH 163/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md index 41ab4778b6..474b736dce 100644 --- a/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md +++ b/docs/docs/resources/azure-ad/AADConditionalAccessPolicy.md @@ -19,10 +19,10 @@ | **IncludeRoles** | Write | StringArray[] | AAD Admin Roles in scope of the Policy. | | | **ExcludeRoles** | Write | StringArray[] | AAD Admin Roles out of scope of the Policy. | | | **IncludeGuestOrExternalUserTypes** | Write | StringArray[] | Represents the Included internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue. | `none`, `internalGuest`, `b2bCollaborationGuest`, `b2bCollaborationMember`, `b2bDirectConnectUser`, `otherExternalUser`, `serviceProvider`, `unknownFutureValue` | -| **IncludeExternalTenantsMembershipKind** | Write | String | Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | `all`, `enumerated`, `unknownFutureValue` | +| **IncludeExternalTenantsMembershipKind** | Write | String | Represents the Included Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | ``, `all`, `enumerated`, `unknownFutureValue` | | **IncludeExternalTenantsMembers** | Write | StringArray[] | Represents the Included collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting. | | | **ExcludeGuestOrExternalUserTypes** | Write | StringArray[] | Represents the Excluded internal guests or external user types. This is a multi-valued property. Supported values are: b2bCollaborationGuest, b2bCollaborationMember, b2bDirectConnectUser, internalGuest, OtherExternalUser, serviceProvider and unknownFutureValue. | `none`, `internalGuest`, `b2bCollaborationGuest`, `b2bCollaborationMember`, `b2bDirectConnectUser`, `otherExternalUser`, `serviceProvider`, `unknownFutureValue` | -| **ExcludeExternalTenantsMembershipKind** | Write | String | Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | `all`, `enumerated`, `unknownFutureValue` | +| **ExcludeExternalTenantsMembershipKind** | Write | String | Represents the Excluded Tenants membership kind. The possible values are: all, enumerated, unknownFutureValue. enumerated references an object of conditionalAccessEnumeratedExternalTenants derived type. | ``, `all`, `enumerated`, `unknownFutureValue` | | **ExcludeExternalTenantsMembers** | Write | StringArray[] | Represents the Excluded collection of tenant ids in the scope of Conditional Access for guests and external users policy targeting. | | | **IncludePlatforms** | Write | StringArray[] | Client Device Platforms in scope of the Policy. | | | **ExcludePlatforms** | Write | StringArray[] | Client Device Platforms out of scope of the Policy. | | From 073b41c01514e9d5881ad4602d94c5b8a2058f1e Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 21 Feb 2024 12:41:56 +0000 Subject: [PATCH 164/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/azure-ad/AADApplication.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/docs/resources/azure-ad/AADApplication.md b/docs/docs/resources/azure-ad/AADApplication.md index 905304b5cc..8dc7751113 100644 --- a/docs/docs/resources/azure-ad/AADApplication.md +++ b/docs/docs/resources/azure-ad/AADApplication.md @@ -8,6 +8,7 @@ | **ObjectId** | Write | String | ObjectID of the app. | | | **AppId** | Write | String | AppId for the app. | | | **AvailableToOtherTenants** | Write | Boolean | Indicates whether this application is available in other tenants. | | +| **Description** | Write | String | A free text field to provide a description of the application object to end users. The maximum allowed size is 1024 characters. | | | **GroupMembershipClaims** | Write | String | A bitmask that configures the groups claim issued in a user or OAuth 2.0 access token that the application expects. | | | **Homepage** | Write | String | The URL to the application's homepage. | | | **IdentifierUris** | Write | StringArray[] | User-defined URI(s) that uniquely identify a Web application within its Azure AD tenant, or within a verified custom domain. | | @@ -91,6 +92,7 @@ Configuration Example { DisplayName = "AppDisplayName" AvailableToOtherTenants = $false + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" @@ -150,6 +152,7 @@ Configuration Example { DisplayName = "AppDisplayName" AvailableToOtherTenants = $true # Updated Property + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" From 8184636d77b35f50bd0f4e0154ba92441bc06710 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 21 Feb 2024 12:44:20 +0000 Subject: [PATCH 165/171] Updated {Create} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 index 0fa22c30a2..088923b9ee 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Create.Tests.ps1 @@ -32,7 +32,7 @@ { DisplayName = "AppDisplayName" AvailableToOtherTenants = $false - Description = 'Test Description' + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" From 82016095e7b4b41dd4ba45a867582c91d55bd7e9 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 21 Feb 2024 12:47:12 +0000 Subject: [PATCH 166/171] Updated {Update} AAD Integration Tests --- .../Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 index 21be834009..6954a18b3e 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.AAD.Update.Tests.ps1 @@ -31,6 +31,7 @@ { DisplayName = "AppDisplayName" AvailableToOtherTenants = $true # Updated Property + Description = "Application Description" GroupMembershipClaims = "None" Homepage = "https://$Domain" IdentifierUris = "https://$Domain" From 7d7fd9261261ab179ff6364f619101272b09da69 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Wed, 21 Feb 2024 13:03:35 +0000 Subject: [PATCH 167/171] Updated {Update} EXO Integration Tests --- .../M365DSCIntegration.EXO.Update.Tests.ps1 | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 index b944ef9129..fc2fbae073 100644 --- a/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 +++ b/Tests/Integration/Microsoft365DSC/M365DSCIntegration.EXO.Update.Tests.ps1 @@ -511,11 +511,11 @@ EXOMailboxPlan 'ConfigureMailboxPlan' { Ensure = "Present"; - Identity = "Integration Plan"; - IssueWarningQuota = "98 GB (105,226,698,752 bytes)"; + Identity = "ExchangeOnlineEssentials"; + IssueWarningQuota = "15 GB (16,106,127,360 bytes)"; MaxReceiveSize = "25 MB (26,214,400 bytes)"; MaxSendSize = "25 MB (26,214,400 bytes)"; - ProhibitSendQuota = "99 GB (106,300,440,576 bytes)"; + ProhibitSendQuota = "15 GB (16,106,127,360 bytes)"; ProhibitSendReceiveQuota = "15 GB (16,106,127,360 bytes)"; # Updated Property RetainDeletedItemsFor = "14.00:00:00"; RoleAssignmentPolicy = "Default Role Assignment Policy"; @@ -523,7 +523,7 @@ } EXOMailboxSettings 'OttawaTeamMailboxSettings' { - DisplayName = 'Ottawa Employees' + DisplayName = 'Conf Room Adams' TimeZone = 'Eastern Standard Time' Locale = 'en-US' # Updated Property Ensure = 'Present' @@ -674,7 +674,7 @@ EXOOfflineAddressBook 'ConfigureOfflineAddressBook' { Name = "Integration Address Book" - AddressLists = @('\Offline Global Address List') + AddressLists = @('\All Users') DiffRetentionPeriod = "30" IsDefault = $false # Updated Property Ensure = "Present" @@ -696,13 +696,13 @@ } EXOOnPremisesOrganization 'ConfigureOnPremisesOrganization' { - Identity = 'Contoso' - Comment = 'Mail for Contoso. Updated' # Updated Property - HybridDomains = 'contoso.com', 'sales.contoso.com' - InboundConnector = 'Inbound to Contoso' - OrganizationGuid = 'a1bc23cb-3456-bcde-abcd-feb363cacc88' - OrganizationName = 'Contoso' - OutboundConnector = 'Outbound to Contoso' + Identity = 'Integration' + Comment = 'Mail for Contoso - Updated' #Updated Property + HybridDomains = 'o365dsc.onmicrosoft.com' + InboundConnector = 'Integration Inbound Connector' + OrganizationGuid = 'e7a80bcf-696e-40ca-8775-a7f85fbb3ebc' + OrganizationName = 'O365DSC' + OutboundConnector = 'Contoso Outbound Connector' Ensure = 'Present' Credential = $Credscredential } @@ -889,14 +889,15 @@ { Name = "HRApp" ApplicationIdentifier = "00000006-0000-0dd1-ac00-000000000000" - Enabled = $False # Updated Property + AcceptSecurityIdentifierInformation = $False # Updated Property + Enabled = $True Ensure = "Present" Credential = $Credscredential } EXOPerimeterConfiguration 'ConfigurePerimeterConfiguration' { IsSingleInstance = 'Yes' - GatewayIPAddresses = '123.0.0.1' + #GatewayIPAddresses = '123.0.0.1' Ensure = 'Present' Credential = $Credscredential } @@ -927,7 +928,7 @@ { EndUserQuarantinePermissionsValue = 87; ESNEnabled = $True; # Updated Property - Identity = "$Domain\DefaultFullAccessPolicy"; + Identity = "$Domain\IntegrationPolicy"; Ensure = "Present" Credential = $Credscredential } @@ -944,9 +945,9 @@ DisplaySenderName = $True DomainName = "contoso.com" IsInternal = $False - LineWrapSize = "Integration" + LineWrapSize = "Unlimited" MeetingForwardNotificationEnabled = $False - Name = "Default" + Name = "Integration" NonMimeCharacterSet = "iso-8859-1" PreferredInternetCodePageForShiftJis = "Undefined" TargetDeliveryDomain = $False @@ -992,8 +993,8 @@ EXORoleAssignmentPolicy 'ConfigureRoleAssignmentPolicy' { Name = "Integration Policy" - Description = "This policy grants end users the permission to set their options in Outlook on the web and perform other self-administration tasks." - IsDefault = $False # Updated Property + Description = "Updated Description" # Updated Property + IsDefault = $True Roles = @("My Marketplace Apps","MyVoiceMail","MyDistributionGroups","MyRetentionPolicies","MyContactInformation","MyBaseOptions","MyTextMessaging","MyDistributionGroupMembership","MyProfileInformation","My Custom Apps","My ReadWriteMailbox Apps") Ensure = "Present" Credential = $Credscredential From 2c11eabbc7f29f7fbac23d169b270e1047b24189 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 21 Feb 2024 13:31:10 -0500 Subject: [PATCH 168/171] Release 1.24.221.1 --- CHANGELOG.md | 23 ++++- ...T_EXOActiveSyncDeviceAccessRule.schema.mof | 1 + ...SFT_EXOAuthenticationPolicyAssignment.psm1 | 9 +- .../MSFT_EXOAvailabilityAddressSpace.psm1 | 5 +- .../MSFT_EXOAvailabilityConfig.psm1 | 3 +- .../MSFT_EXOCASMailboxPlan.psm1 | 31 +++++- .../MSFT_EXOCASMailboxPlan.schema.mof | 1 + .../MSFT_EXODataClassification.psm1 | 63 +++++++------ .../MSFT_EXOGroupSettings.psm1 | 26 ++++- .../MSFT_EXOGroupSettings.schema.mof | 1 + ...MSFT_EXOMailboxAutoReplyConfiguration.psm1 | 31 ++++-- ...XOMailboxAutoReplyConfiguration.schema.mof | 1 + .../MSFT_EXOMailboxPlan.psm1 | 25 ++++- .../MSFT_EXOMailboxPlan.schema.mof | 1 + .../MSFT_EXOMailboxSettings.psm1 | 23 ++++- .../MSFT_EXOMessageClassification.psm1 | 58 +++++++----- .../MSFT_EXOPlace/MSFT_EXOPlace.psm1 | 94 +++++++++++-------- .../MSFT_EXOPlace/MSFT_EXOPlace.schema.mof | 1 + .../MSFT_EXORecipientPermission.psm1 | 27 +++++- .../MSFT_EXOSharedMailbox.psm1 | 63 +++++++++++-- .../MSFT_EXOSharedMailbox.schema.mof | 1 + ...AdministrativeTemplatePolicyWindows10.psm1 | 2 +- Modules/Microsoft365DSC/Microsoft365DSC.psd1 | 62 ++++++------ .../Microsoft365DSC/Modules/M365DSCAgent.psm1 | 2 +- .../Modules/M365DSCReport.psm1 | 51 +++++----- .../Modules/M365DSCTelemetryEngine.psm1 | 2 +- .../Microsoft365DSC/Modules/M365DSCUtil.psm1 | 2 +- 27 files changed, 421 insertions(+), 188 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aee82f2307..ccf854bd31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change log for Microsoft365DSC -# UNRELEASED +# 1.24.221.1 * AADApplication * Expose the description field in the resource. @@ -10,6 +10,27 @@ FIXES [#4347](https://github.com/microsoft/Microsoft365DSC/issues/4347) * Throws an error if role, user or group was not found in the Set method. FIXES [#4342](https://github.com/microsoft/Microsoft365DSC/issues/4342) +* EXOAuthenticationPolicyAssignment + * Improved performance by using a filter to retrieve assignments. + * Export now retrieves the user principal name instead of the user id. +* EXOAvailabilityConfig + * Export now retrieves the user principal name instead of the user id. +* EXOCASMailboxPlan + * Added the DisplayName property. +* EXODataClassification + * Added logic to retrieve by name in the GET method if no match found by id. +* EXOMailboxAutoReplyConfiguration + * Added the owner property. +* EXOMailboxPlan + * Added the DisplayName property. +* EXOMailboxSettings + * Export now retrieves instances by User Principal Name instead of GUID. +* EXOPlace + * Added the DisplayName property. +* EXORecipientPermission + * Export now retrieves instances by User Principal Name instead of GUID. +* EXOSharedMailbox + * Added the Identity parameter. * MISC * Uninstall-M365DSCOutdatedDependencies * Outdated Microsoft365DSC-modules are now removed in their entirety diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOActiveSyncDeviceAccessRule/MSFT_EXOActiveSyncDeviceAccessRule.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOActiveSyncDeviceAccessRule/MSFT_EXOActiveSyncDeviceAccessRule.schema.mof index 1da0ec571b..7fec77b681 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOActiveSyncDeviceAccessRule/MSFT_EXOActiveSyncDeviceAccessRule.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOActiveSyncDeviceAccessRule/MSFT_EXOActiveSyncDeviceAccessRule.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOActiveSyncDeviceAccessRule : OMI_BaseResource { [Key, Description("The Identity parameter specifies the identity of the device access rule.")] String Identity; + [Write, Description("Unique Identifier. Read-Only")] String GUID; [Write, Description("The AccessLevel parameter specifies whether the devices are allowed, blocked or quarantined."), ValueMap{"Allow","Block","Quarantine"}, Values{"Allow","Block","Quarantine"}] String AccessLevel; [Write, Description("The Characteristic parameter specifies the device characteristic or category that's used by the rule."), ValueMap{"DeviceModel","DeviceType","DeviceOS","UserAgent","XMSWLHeader"}, Values{"DeviceModel","DeviceType","DeviceOS","UserAgent","XMSWLHeader"}] String Characteristic; [Write, Description("The QueryString parameter specifies the device identifier that's used by the rule. This parameter uses a text value that's used with Characteristic parameter value to define the device.")] String QueryString; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicyAssignment/MSFT_EXOAuthenticationPolicyAssignment.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicyAssignment/MSFT_EXOAuthenticationPolicyAssignment.psm1 index 2ccb9b40a1..47637d5b3c 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicyAssignment/MSFT_EXOAuthenticationPolicyAssignment.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAuthenticationPolicyAssignment/MSFT_EXOAuthenticationPolicyAssignment.psm1 @@ -346,20 +346,15 @@ function Export-TargetResource Write-Host "`r`n" -NoNewline } $i = 1 - $allUsers = $null foreach ($AuthenticationPolicy in $AllAuthenticationPolicies) { Write-Host " |---[$i/$($AllAuthenticationPolicies.Count)] $($AuthenticationPolicy.Identity)" -NoNewline - if (-not $allUsers) - { - $allUsers = Get-User -ResultSize 'Unlimited' - } - $assignedUsers = $allUsers | Where-Object -FilterScript { $_.AuthenticationPolicy -eq $AuthenticationPolicy.Identity } + $assignedUsers = Get-User -Filter "AuthenticationPolicy -eq '$($AuthenticationPolicy.DistinguishedName)'" foreach ($user in $assignedUsers) { $Params = @{ - UserName = $user.Name + UserName = $user.UserPrincipalName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 index d7f80154ca..9ac8cba208 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityAddressSpace/MSFT_EXOAvailabilityAddressSpace.psm1 @@ -99,7 +99,10 @@ function Get-TargetResource { try { - $AvailabilityAddressSpace = Get-AvailabilityAddressSpace -Identity $ForestName -ErrorAction Stop + if (-not [System.String]::IsNullOrEmpty($ForestName)) + { + $AvailabilityAddressSpace = Get-AvailabilityAddressSpace -Identity $ForestName -ErrorAction Stop + } } catch { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 index a0d4e1ad4f..7c169b1fd9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOAvailabilityConfig/MSFT_EXOAvailabilityConfig.psm1 @@ -346,7 +346,8 @@ function Export-TargetResource $OrgWideValue = "NotConfigured" if ($null -ne $AvailabilityConfig.OrgWideAccount) { - $OrgWideValue = $AvailabilityConfig.OrgWideAccount.ToString() + $user = Get-User -Identity $AvailabilityConfig.OrgWideAccount.ToString() + $OrgWideValue = $user.UserPrincipalName } $Params = @{ OrgWideAccount = $OrgWideValue diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.psm1 index e040da9695..d31632afad 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [Boolean] $ActiveSyncEnabled = $true, @@ -95,16 +99,26 @@ function Get-TargetResource { Write-Verbose -Message "MailboxPlan $($Identity) does not exist." - $CASMailboxPlan = Get-CASMailboxPlan -Filter "Name -like '$($Identity.Split('-')[0])-*'" - if ($null -eq $CASMailboxPlan) + # Try and retrieve by Display Name + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + $CASMailboxPlan = Get-CASMailboxPlan -Filter "DisplayName -eq '$DisplayName'" + } + + if ($null -eq $MailboxPlan) { - Write-Verbose -Message "CASMailboxPlan $($Identity) does not exist." - return $nullResult + $CASMailboxPlan = Get-CASMailboxPlan -Filter "Name -like '$($Identity.Split('-')[0])-*'" + if ($null -eq $CASMailboxPlan) + { + Write-Verbose -Message "CASMailboxPlan $($Identity) does not exist." + return $nullResult + } } } $result = @{ Identity = $Identity + DisplayName = $CASMailboxPlan.DisplayName ActiveSyncEnabled = $CASMailboxPlan.ActiveSyncEnabled ImapEnabled = $CASMailboxPlan.ImapEnabled OwaMailboxPolicy = $CASMailboxPlan.OwaMailboxPolicy @@ -143,6 +157,10 @@ function Set-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [Boolean] $ActiveSyncEnabled = $true, @@ -244,6 +262,10 @@ function Test-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [Boolean] $ActiveSyncEnabled = $true, @@ -394,6 +416,7 @@ function Export-TargetResource Write-Host " |---[$i/$($CASMailboxPlans.Count)] $($CASMailboxPlan.Identity.Split('-')[0])" -NoNewline $Params = @{ Identity = $CASMailboxPlan.Identity + DisplayName = $CASMailboxPlan.DisplayName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.schema.mof index 47e369fab8..12e4473afc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOCASMailboxPlan/MSFT_EXOCASMailboxPlan.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOCASMailboxPlan : OMI_BaseResource { [Key, Description("The Identity parameter specifies the CAS Mailbox Plan that you want to modify.")] String Identity; + [Write, Description("The display name of the CAS Mailbox Plan.")] String DisplayName; [Write, Description("CASMailboxPlans cannot be created/removed in O365. This must be set to 'Present'"), ValueMap{"Present"}, Values{"Present"}] String Ensure; [Write, Description("The ActiveSyncEnabled parameter enables or disables access to the mailbox by using Exchange Active Sync. Default is $true.")] Boolean ActiveSyncEnabled; [Write, Description("The ImapEnabled parameter enables or disables access to the mailbox by using IMAP4 clients. The default value is $true for all CAS mailbox plans except ExchangeOnlineDeskless which is $false by default.")] Boolean ImapEnabled; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 index 2754f2074f..eeaad10a38 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 @@ -102,41 +102,46 @@ function Get-TargetResource } if ($null -eq $DataClassification) { - Write-Verbose -Message "Data classification $($Identity) does not exist." - return $nullReturn - } - else - { - - $currentDefaultCultureName = ([system.globalization.cultureinfo]$DataClassification.DefaultCulture).Name - $DataClassificationLocale = $currentDefaultCultureName - $DataClassificationIsDefault = $false - if (([String]::IsNullOrEmpty($Locale)) -or ($Locale -eq $currentDefaultCultureName)) + if (-not [System.String]::IsNullOrEmpty($Name)) { - $DataClassificationIsDefault = $true + Write-Verbose -Message "Couldn't retrieve data classification by Identity. Trying by Name {$Name}." + $DataClassification = Get-DataClassification -Identity $Name } - $result = @{ - Identity = $Identity - Description = $DataClassification.Description - Fingerprints = $DataClassification.Fingerprints - IsDefault = $DataClassificationIsDefault - Locale = $DataClassificationLocale - Name = $DataClassification.Name - Credential = $Credential - Ensure = 'Present' - ApplicationId = $ApplicationId - CertificateThumbprint = $CertificateThumbprint - CertificatePath = $CertificatePath - CertificatePassword = $CertificatePassword - ManagedIdentity = $ManagedIdentity.IsPresent - TenantId = $TenantId + if ($null -eq $DataClassification) + { + Write-Verbose -Message "Data classification $($Identity) does not exist." + return $nullReturn } + } + $currentDefaultCultureName = ([system.globalization.cultureinfo]$DataClassification.DefaultCulture).Name + $DataClassificationLocale = $currentDefaultCultureName + $DataClassificationIsDefault = $false + if (([String]::IsNullOrEmpty($Locale)) -or ($Locale -eq $currentDefaultCultureName)) + { + $DataClassificationIsDefault = $true + } - Write-Verbose -Message "Found Data classification policy $($Identity)" - Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" - return $result + $result = @{ + Identity = $Identity + Description = $DataClassification.Description + Fingerprints = $DataClassification.Fingerprints + IsDefault = $DataClassificationIsDefault + Locale = $DataClassificationLocale + Name = $DataClassification.Name + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + ManagedIdentity = $ManagedIdentity.IsPresent + TenantId = $TenantId } + + Write-Verbose -Message "Found Data classification policy $($Identity)" + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result } catch { diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.psm1 index 4772c7646b..f1f60fd6db 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Id, + [Parameter()] [System.String[]] $AcceptMessagesOnlyFromSendersOrMembers, @@ -273,12 +277,20 @@ function Get-TargetResource { if ($null -ne $Script:exportedInstances -and $Script:ExportMode) { - [Array]$group = $Script:exportedInstances | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} + [Array]$group = $Script:exportedInstances | Where-Object -FilterScript {$_.Id -eq $Id} } else { - [Array]$group = Get-UnifiedGroup -Identity $DisplayName -IncludeAllProperties -ErrorAction Stop + Write-Verbose -Message "Retrieving group by id {$Id}" + [Array]$group = Get-UnifiedGroup -Identity $Id -IncludeAllProperties -ErrorAction Stop + + if ($group.Length -eq 0) + { + Write-Verbose -Message "Couldn't retrieve group by ID. Trying by DisplayName {$DisplayName}" + [Array]$group = Get-UnifiedGroup -Identity $DisplayName -IncludeAllProperties -ErrorAction Stop + } } + if ($group.Length -gt 1) { Write-Warning -Message "Multiple instances of a group named {$DisplayName} was discovered which could result in inconsistencies retrieving its values." @@ -298,6 +310,7 @@ function Get-TargetResource $result = @{ DisplayName = $DisplayName + Id = $group.Id AcceptMessagesOnlyFromSendersOrMembers = $group.AcceptMessagesOnlyFromSendersOrMembers AccessType = $group.AccessType AlwaysSubscribeMembersToCalendarEvents = $group.AlwaysSubscribeMembersToCalendarEvents @@ -370,6 +383,10 @@ function Set-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Id, + [Parameter()] [System.String[]] $AcceptMessagesOnlyFromSendersOrMembers, @@ -646,6 +663,10 @@ function Test-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Id, + [Parameter()] [System.String[]] $AcceptMessagesOnlyFromSendersOrMembers, @@ -979,6 +1000,7 @@ function Export-TargetResource $Params = @{ Credential = $Credential DisplayName = $groupName + Id = $group.Id ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.schema.mof index 4e43097540..5e8f2b60c2 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOGroupSettings/MSFT_EXOGroupSettings.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOGroupSettings : OMI_BaseResource { [Key, Description("The DisplayName parameter specifies the name of the Microsoft 365 Group. The display name is visible in the Exchange admin center, address lists, and Outlook. The maximum length is 64 characters.")] string DisplayName; + [Write, Description("The unique Id of the group")] string Id; [Write, Description("The AcceptMessagesOnlyFromSendersOrMembers parameter specifies who is allowed to send messages to this recipient. Messages from other senders are rejected.")] string AcceptMessagesOnlyFromSendersOrMembers[]; [Write, Description("Private"), ValueMap{"Public","Private"}, Values{"Public","Private"}] string AccessType; [Write, Description("The AlwaysSubscribeMembersToCalendarEvents switch controls the default subscription settings of new members that are added to the Microsoft 365 Group. Changing this setting doesn't affect existing group members.")] boolean AlwaysSubscribeMembersToCalendarEvents; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.psm1 index b46168f28c..cf161b5301 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $Owner, + [Parameter()] [System.Boolean] $AutoDeclineFutureRequestsWhenOOF, @@ -135,8 +139,10 @@ function Get-TargetResource } else { + $ownerValue = Get-User -Identity $config.Identity $result = @{ Identity = $config.Identity + Owner = $ownerValue.UserPrincipalName AutoDeclineFutureRequestsWhenOOF = [Boolean]$config.AutoDeclineFutureRequestsWhenOOF AutoReplyState = $config.AutoReplyState CreateOOFEvent = [Boolean]$config.CreateOOFEvent @@ -150,14 +156,14 @@ function Get-TargetResource InternalMessage = $config.InternalMessage OOFEventSubject = $config.OOFEventSubject StartTime = $config.StartTime - Credential = $Credential - Ensure = 'Present' - ApplicationId = $ApplicationId - CertificateThumbprint = $CertificateThumbprint - CertificatePath = $CertificatePath - CertificatePassword = $CertificatePassword - Managedidentity = $ManagedIdentity.IsPresent - TenantId = $TenantId + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId } Write-Verbose -Message "Found Mailbox $($Identity)" @@ -186,6 +192,10 @@ function Set-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $Owner, + [Parameter()] [System.Boolean] $AutoDeclineFutureRequestsWhenOOF, @@ -299,6 +309,7 @@ function Set-TargetResource $PSBoundParameters.Remove('ManagedIdentity') | Out-Null $PSBoundParameters.Remove('CertificatePath') | Out-Null $PSBoundParameters.Remove('Credential') | Out-Null + $PSBoundParameters.Remove('Owner') | Out-Null Set-MailboxAutoReplyConfiguration @PSBoundParameters } @@ -313,6 +324,10 @@ function Test-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $Owner, + [Parameter()] [System.Boolean] $AutoDeclineFutureRequestsWhenOOF, diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.schema.mof index 4c9de449d7..4978fd8cb9 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxAutoReplyConfiguration/MSFT_EXOMailboxAutoReplyConfiguration.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOMailboxAutoReplyConfiguration : OMI_BaseResource { [Key, Description("The Identity parameter specifies the mailbox that you want to modify. You can use any value that uniquely identifies the mailbox.")] String Identity; + [Write, Description("User Principal Name of the mailbox owner")] String Owner; [Write, Description("The AutoDeclineFutureRequestsWhenOOF parameter specifies whether to automatically decline new meeting requests that are sent to the mailbox during the scheduled time period when Automatic Replies are being sent. ")] Boolean AutoDeclineFutureRequestsWhenOOF; [Write, Description("The AutoReplyState parameter specifies whether the mailbox is enabled for Automatic Replies. Valid values are: Enabled, Disabled, Scheduled"), ValueMap{"Enabled", "Disabled", "Scheduled"}, Values{"Enabled", "Disabled", "Scheduled"}] String AutoReplyState; [Write, Description("The CreateOOFEvent parameter specifies whether to create a calendar event that corresponds to the scheduled time period when Automatic Replies are being sent for the mailbox.")] Boolean CreateOOFEvent; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.psm1 index 9c2fbb2a62..dc31ffc3fc 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $IssueWarningQuota, @@ -110,9 +114,16 @@ function Get-TargetResource if ($null -eq $MailboxPlan) { - Write-Verbose -Message "MailboxPlan $($Identity) does not exist." + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + Write-Verbose -Message "Couldn't find MailboxPlan by Identity {$Identity}. Trying by DisplayName." + $MailboxPlan = Get-MailboxPlan -Identity $DisplayName + } + else + { + $MailboxPlan = Get-MailboxPlan -Filter "Name -like '$($Identity.Split('-')[0])*'" + } - $MailboxPlan = Get-MailboxPlan -Filter "Name -like '$($Identity.Split('-')[0])*'" if ($null -eq $MailboxPlan) { return $nullResult @@ -121,6 +132,7 @@ function Get-TargetResource $result = @{ Identity = $Identity + DisplayName = $MailboxPlan.DisplayName IssueWarningQuota = $MailboxPlan.IssueWarningQuota MaxReceiveSize = $MailboxPlan.MaxReceiveSize MaxSendSize = $MailboxPlan.MaxSendSize @@ -163,6 +175,10 @@ function Set-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $IssueWarningQuota, @@ -279,6 +295,10 @@ function Test-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $IssueWarningQuota, @@ -445,6 +465,7 @@ function Export-TargetResource Write-Host " |---[$i/$($MailboxPlans.Count)] $($MailboxPlan.Identity.Split('-')[0])" -NoNewline $Params = @{ Identity = $MailboxPlan.Identity + DisplayName = $MailboxPlan.DisplayName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof index da53fc80a6..b64646139d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOMailboxPlan : OMI_BaseResource { [Key, Description("The Identity parameter specifies the Mailbox Plan that you want to modify.")] String Identity; + [Key, Description("The display name of the mailbox plan.")] String DisplayName; [Write, Description("MailboxPlans cannot be created/removed in O365. This must be set to 'Present'"), ValueMap{"Present"}, Values{"Present"}] String Ensure; [Write, Description("The IssueWarningQuota parameter specifies the warning threshold for the size of the mailboxes that are created or enabled using the mailbox plan.")] String IssueWarningQuota; [Write, Description("The MaxReceiveSize parameter specifies the maximum size of a message that can be sent to the mailbox.")] String MaxReceiveSize; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxSettings/MSFT_EXOMailboxSettings.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxSettings/MSFT_EXOMailboxSettings.psm1 index 3f08f269a1..ccf40691ac 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxSettings/MSFT_EXOMailboxSettings.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxSettings/MSFT_EXOMailboxSettings.psm1 @@ -338,15 +338,30 @@ function Export-TargetResource Write-Host "`r`n"-NoNewline } $dscContent = '' + $ObjectGuid = [System.Guid]::empty foreach ($mailbox in $mailboxes) { - Write-Host " |---[$i/$($mailboxes.Length)] $($mailbox.Name)" -NoNewline - $mailboxName = $mailbox.Name - if (-not [System.String]::IsNullOrEmpty($mailboxName)) + $DisplayNameValue = $mailbox.Name + + if ([System.Guid]::TryParse($mailbox.Identity,[System.Management.Automation.PSReference]$ObjectGuid)) + { + try + { + $user = Get-User -Identity $mailbox.Identity + $DisplayNameValue = $user.UserPrincipalName + } + catch + { + Write-Verbose -Message "Could not retrieve user with id {$($mailbox.Identity)}" + } + } + Write-Host " |---[$i/$($mailboxes.Length)] $($DisplayNameValue)" -NoNewline + + if (-not [System.String]::IsNullOrEmpty($DisplayNameValue)) { $Params = @{ Credential = $Credential - DisplayName = $mailbox.Name + DisplayName = $DisplayNameValue ApplicationId = $ApplicationId TenantId = $TenantId CertificateThumbprint = $CertificateThumbprint diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 index 8b49da6bed..c277a31175 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMessageClassification/MSFT_EXOMessageClassification.psm1 @@ -109,35 +109,40 @@ function Get-TargetResource if ($null -eq $MessageClassification) { - Write-Verbose -Message "Message Classification policy $($Identity) does not exist." - return $nullReturn - } - else - { - $result = @{ - Identity = $Identity - ClassificationID = $MessageClassification.ClassificationID - DisplayName = $MessageClassification.DisplayName - DisplayPrecedence = $MessageClassification.DisplayPrecedence - Name = $MessageClassification.Name - PermissionMenuVisible = $MessageClassification.PermissionMenuVisible - RecipientDescription = $MessageClassification.RecipientDescription - RetainClassificationEnabled = $MessageClassification.RetainClassificationEnabled - SenderDescription = $MessageClassification.SenderDescription - Credential = $Credential - Ensure = 'Present' - ApplicationId = $ApplicationId - CertificateThumbprint = $CertificateThumbprint - CertificatePath = $CertificatePath - CertificatePassword = $CertificatePassword - Managedidentity = $ManagedIdentity.IsPresent - TenantId = $TenantId + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + Write-Verbose -Message "Couldn't retrieve Message Classification policy by Id {$($Identity)}. Trying by DisplayName." + $MessageClassification = Get-MessageClassification -Identity $DisplayName } + if ($null -eq $MessageClassification) + { + return $nullReturn + } + } - Write-Verbose -Message "Found Message Classification policy $($Identity)" - Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" - return $result + $result = @{ + Identity = $Identity + ClassificationID = $MessageClassification.ClassificationID + DisplayName = $MessageClassification.DisplayName + DisplayPrecedence = $MessageClassification.DisplayPrecedence + Name = $MessageClassification.Name + PermissionMenuVisible = $MessageClassification.PermissionMenuVisible + RecipientDescription = $MessageClassification.RecipientDescription + RetainClassificationEnabled = $MessageClassification.RetainClassificationEnabled + SenderDescription = $MessageClassification.SenderDescription + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId } + + Write-Verbose -Message "Found Message Classification policy $($Identity)" + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + return $result } catch { @@ -494,6 +499,7 @@ function Export-TargetResource $Params = @{ Identity = $MessageClassification.Identity + DisplayName = $MessageClassification.Name Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 index 2829411355..f9c655fb43 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $AudioDeviceName, @@ -161,47 +165,52 @@ function Get-TargetResource if ($null -eq $place) { - Write-Verbose -Message "Place $($Identity) does not exist." - return $nullReturn - } - else - { - $result = @{ - Identity = $place.Identity - AudioDeviceName = $place.AudioDeviceName - Building = $place.Building - Capacity = $place.Capacity - City = $place.City - CountryOrRegion = $place.CountryOrRegion - Desks = [Array] $place.Desks - DisplayDeviceName = $place.DisplayDeviceName - Floor = $place.Floor - FloorLabel = $place.FloorLabel - GeoCoordinates = $place.GeoCoordinates - IsWheelChairAccessible = [Boolean] $place.IsWheelChairAccessible - Label = $place.Label - MTREnabled = [Boolean] $place.MTREnabled - ParentId = $place.ParentId - ParentType = $place.ParentType - Phone = $place.Phone - PostalCode = $place.PostalCode - State = $place.State - Street = $place.Street - Tags = [Array] $place.Tags - VideoDeviceName = $place.VideoDeviceName - Credential = $Credential - Ensure = 'Present' - ApplicationId = $ApplicationId - CertificateThumbprint = $CertificateThumbprint - CertificatePath = $CertificatePath - CertificatePassword = $CertificatePassword - Managedidentity = $ManagedIdentity.IsPresent - TenantId = $TenantId + if (-not [System.String]::IsNullOrEmpty($DisplayName)) + { + Write-Verbose -Message "Couldn't retrieve place by Id {$($Identity)}. Trying by DisplayName" + $place = Get-Place -ResultSize 'Unlimited' | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} } - Write-Verbose -Message "Found Place $($Identity)" - return $result + if ($null -eq $place) + { + return $nullReturn + } } + + $result = @{ + Identity = $place.Identity + AudioDeviceName = $place.AudioDeviceName + Building = $place.Building + Capacity = $place.Capacity + City = $place.City + CountryOrRegion = $place.CountryOrRegion + Desks = [Array] $place.Desks + DisplayDeviceName = $place.DisplayDeviceName + DisplayName = $place.DisplayName + Floor = $place.Floor + FloorLabel = $place.FloorLabel + GeoCoordinates = $place.GeoCoordinates + IsWheelChairAccessible = [Boolean] $place.IsWheelChairAccessible + Label = $place.Label + MTREnabled = [Boolean] $place.MTREnabled + ParentId = $place.ParentId + ParentType = $place.ParentType + Phone = $place.Phone + PostalCode = $place.PostalCode + State = $place.State + Street = $place.Street + Tags = [Array] $place.Tags + VideoDeviceName = $place.VideoDeviceName + Credential = $Credential + Ensure = 'Present' + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + } + return $result } catch { @@ -224,6 +233,10 @@ function Set-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $AudioDeviceName, @@ -386,6 +399,10 @@ function Test-TargetResource [System.String] $Identity, + [Parameter()] + [System.String] + $DisplayName, + [Parameter()] [System.String] $AudioDeviceName, @@ -604,6 +621,7 @@ function Export-TargetResource $Params = @{ Identity = $place.Identity + DisplayName = $place.DisplayName Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof index 5d63f2ea12..f258ea8785 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOPlace/MSFT_EXOPlace.schema.mof @@ -3,6 +3,7 @@ class MSFT_EXOPlace : OMI_BaseResource { [Key, Description("The Identity parameter specifies the room mailbox that you want to modify. You can use any value that uniquely identifies the room.")] String Identity; + [Write, Description("The display name of the place.")] String DisplayName; [Write, Description("The AudioDeviceName parameter specifies the name of the audio device in the room. If the value contains spaces, enclose the value in quotation marks.")] String AudioDeviceName; [Write, Description("The Building parameter specifies the building name or building number that the room is in. If the value contains spaces, enclose the value in quotation marks.")] String Building; [Write, Description("The Capacity parameter specifies the capacity of the room. A valid value is an integer.")] UInt32 Capacity; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 index 06759e50af..3613adcd20 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXORecipientPermission/MSFT_EXORecipientPermission.psm1 @@ -87,6 +87,21 @@ function Get-TargetResource $recipientPermission = $Script:recipientPermissions | Where-Object -FilterScript { $_.Identity -eq $Identity -and $_.Trustee -eq $Trustee -and $_.AccessRights -eq $AccessRights } + + if ($null -eq $recipientPermission) + { + try + { + $userValue = Get-User -Identity $Identity + $recipientPermission = $Script:recipientPermissions | Where-Object -FilterScript { + $_.Identity -eq $userValue.Identity -and $_.Trustee -eq $Trustee -and $_.AccessRights -eq $AccessRights + } + } + catch + { + Write-Verbose -Message $_ + } + } } else { @@ -411,15 +426,21 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } + $ObjectGuid = [System.Guid]::empty foreach ($recipientPermission in $recipientPermissions) { - Write-Host " |---[$i/$($recipientPermissions.Length)] $($recipientPermission.Identity)" -NoNewline + $IdentityValue = $recipientPermission.Identity + if ([System.Guid]::TryParse($IdentityValue,[System.Management.Automation.PSReference]$ObjectGuid)) + { + $user = Get-User -Identity $IdentityValue + $IdentityValue = $user.UserPrincipalName + } + Write-Host " |---[$i/$($recipientPermissions.Length)] $($IdentityValue)" -NoNewline $params = @{ - Identity = $recipientPermission.Identity + Identity = $IdentityValue Trustee = $recipientPermission.Trustee AccessRights = $recipientPermission.AccessRights - Credential = $Credential ApplicationId = $ApplicationId TenantId = $TenantId diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.psm1 index 5f0225ed8e..41ea881974 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.psm1 @@ -8,6 +8,10 @@ function Get-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Identity, + [Parameter()] [System.String] $PrimarySMTPAddress, @@ -84,10 +88,42 @@ function Get-TargetResource try { - $mailbox = Get-Mailbox -Identity $DisplayName ` - -RecipientTypeDetails 'SharedMailbox' ` - -ResultSize Unlimited ` - -ErrorAction Stop + try + { + if (-not [System.String]::IsNullOrEmpty($Identity)) + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $mailbox = $Script:exportedInstances | Where-Object -FilterScript {$_.Identity -eq $Identity} + } + else + { + $mailbox = $mailbox = Get-Mailbox -Identity $Identity ` + -RecipientTypeDetails 'SharedMailbox' ` + -ResultSize Unlimited ` + -ErrorAction Stop + } + } + + if ($null -eq $mailbox) + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $mailbox = $Script:exportedInstances | Where-Object -FilterScript {$_.DisplayName -eq $DisplayName} + } + else + { + $mailbox = $mailbox = Get-Mailbox -Identity $DisplayName ` + -RecipientTypeDetails 'SharedMailbox' ` + -ResultSize Unlimited ` + -ErrorAction Stop + } + } + } + catch + { + Write-Verbose -Message "Could not retrieve AAD roledefinition by Id: {$Id}" + } if ($null -eq $mailbox) { @@ -110,6 +146,7 @@ function Get-TargetResource $result = @{ DisplayName = $DisplayName + Identity = $mailbox.Identity PrimarySMTPAddress = $mailbox.PrimarySMTPAddress.ToString() Alias = $mailbox.Alias EmailAddresses = $CurrentEmailAddresses @@ -147,6 +184,10 @@ function Set-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Identity, + [Parameter()] [System.String] $PrimarySMTPAddress, @@ -324,6 +365,10 @@ function Test-TargetResource [System.String] $DisplayName, + [Parameter()] + [System.String] + $Identity, + [Parameter()] [System.String] $PrimarySMTPAddress, @@ -454,12 +499,13 @@ function Export-TargetResource try { - [array]$mailboxes = Get-Mailbox -RecipientTypeDetails 'SharedMailbox' ` + $Script:ExportMode = $true + [array] $Script:exportedInstances = Get-Mailbox -RecipientTypeDetails 'SharedMailbox' ` -ResultSize Unlimited ` -ErrorAction Stop $dscContent = '' $i = 1 - if ($mailboxes.Length -eq 0) + if ($Script:exportedInstances.Length -eq 0) { Write-Host $Global:M365DSCEmojiGreenCheckMark } @@ -467,13 +513,14 @@ function Export-TargetResource { Write-Host "`r`n" -NoNewline } - foreach ($mailbox in $mailboxes) + foreach ($mailbox in $Script:exportedInstances) { - Write-Host " |---[$i/$($mailboxes.Length)] $($mailbox.Name)" -NoNewline + Write-Host " |---[$i/$($Script:exportedInstances.Length)] $($mailbox.Name)" -NoNewline $mailboxName = $mailbox.Name if ($mailboxName) { $params = @{ + Identity = $mailbox.Identity Credential = $Credential DisplayName = $mailboxName Alias = $mailbox.Alias diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.schema.mof index d9681da471..ca4d711875 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOSharedMailbox/MSFT_EXOSharedMailbox.schema.mof @@ -2,6 +2,7 @@ class MSFT_EXOSharedMailbox : OMI_BaseResource { [Key, Description("The display name of the Shared Mailbox")] string DisplayName; + [Write, Description("The unique identifier of the Shared Mailbox")] string Identity; [Write, Description("The primary email address of the Shared Mailbox")] string PrimarySMTPAddress; [Write, Description("The alias of the Shared Mailbox")] string Alias; [Write, Description("The EmailAddresses parameter specifies all the email addresses (proxy addresses) for the Shared Mailbox")] string EmailAddresses[]; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10.psm1 index 53512b6e8e..14affae7de 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10/MSFT_IntuneDeviceConfigurationAdministrativeTemplatePolicyWindows10.psm1 @@ -241,7 +241,7 @@ function Get-TargetResource } $results.Add('Assignments', $assignmentResult) - return [System.Collections.Hashtable] $results + return $results } catch { diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 468761965e..78deeb1f7e 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -3,7 +3,7 @@ # # Generated by: Microsoft Corporation # -# Generated on: 2024-02-20 +# Generated on: 2024-02-21 @{ @@ -11,7 +11,7 @@ # RootModule = '' # Version number of this module. - ModuleVersion = '1.24.214.3' + ModuleVersion = '1.24.221.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -140,32 +140,38 @@ IconUri = 'https://github.com/microsoft/Microsoft365DSC/blob/Dev/Modules/Microsoft365DSC/Dependencies/Images/Logo.png?raw=true' # ReleaseNotes of this module - ReleaseNotes = '* AADAuthenticationMethodPolicy - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyAuthenticator - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyEmail - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyFido2 - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicySms - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicySoftware - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyTemporary - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyVoice - * Fixed an error where the Export method would loop through the response header. - * AADAuthenticationMethodPolicyX509 - * Fixed an error where the Export method would loop through the response header. - * IntuneAppConfigurationPolicy - * Fixed an error in the export on the Settings property. - * IntuneDeviceEnrollmentStatusPageWindows10 - * Fixed an error where the Export method would loop through the response header. - * IntuneWindowsAutopilotDeploymentProfileAzureADJoined - * Fixed an error where the Export method would loop through the response header. - * DEPENDENCIES - * Updated Microsoft.Graph to version 2.14.1.' + ReleaseNotes = '* AADApplication + * Expose the description field in the resource. + * AADConditionalAccessPolicy + * Fixing issue where Membership kinds no longer accepted empty values. + ROLLING BACK [#4344](https://github.com/microsoft/Microsoft365DSC/issues/4344) + FIXES [#4347](https://github.com/microsoft/Microsoft365DSC/issues/4347) + * Throws an error if role, user or group was not found in the Set method. + FIXES [#4342](https://github.com/microsoft/Microsoft365DSC/issues/4342) + * EXOAuthenticationPolicyAssignment + * Improved performance by using a filter to retrieve assignments. + * Export now retrieves the user principal name instead of the user id. + * EXOAvailabilityConfig + * Export now retrieves the user principal name instead of the user id. + * EXOCASMailboxPlan + * Added the DisplayName property. + * EXODataClassification + * Added logic to retrieve by name in the GET method if no match found by id. + * EXOMailboxAutoReplyConfiguration + * Added the owner property. + * EXOMailboxPlan + * Added the DisplayName property. + * EXOMailboxSettings + * Export now retrieves instances by User Principal Name instead of GUID. + * EXOPlace + * Added the DisplayName property. + * EXORecipientPermission + * Export now retrieves instances by User Principal Name instead of GUID. + * EXOSharedMailbox + * Added the Identity parameter. + * MISC + * Uninstall-M365DSCOutdatedDependencies + * Outdated Microsoft365DSC-modules are now removed in their entirety.' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false diff --git a/Modules/Microsoft365DSC/Modules/M365DSCAgent.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCAgent.psm1 index 184fa7a787..125f753259 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCAgent.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCAgent.psm1 @@ -20,7 +20,7 @@ function Test-M365DSCAgent #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Event', 'TestAgent') - Add-M365DSCTelemetryEvent -Data $data + Add-M365DSCTelemetryEvent -Data $data -Type 'TestAgent' #endregion [array]$Recommendations = @() diff --git a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 index db573948a1..0e2a98ed35 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCReport.psm1 @@ -522,34 +522,41 @@ function New-M365DSCReportFromConfiguration $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Event', 'Report') $data.Add('Type', $Type) - Add-M365DSCTelemetryEvent -Data $data + Add-M365DSCTelemetryEvent -Data $data -Type 'NewReport' #endregion [Array] $parsedContent = Initialize-M365DSCReporting -ConfigurationPath $ConfigurationPath - switch ($Type) + if ($null -ne $parsedContent) { - 'Excel' + switch ($Type) { - New-M365DSCConfigurationToExcel -ParsedContent $parsedContent -OutputPath $OutputPath - } - 'HTML' - { - $template = Get-Item $ConfigurationPath - $templateName = $Template.Name.Split('.')[0] - New-M365DSCConfigurationToHTML -ParsedContent $parsedContent -OutputPath $OutputPath -TemplateName $templateName - } - 'JSON' - { - New-M365DSCConfigurationToJSON -ParsedContent $parsedContent -OutputPath $OutputPath - } - 'Markdown' - { - $template = Get-Item $ConfigurationPath - $templateName = $Template.Name.Split('.')[0] - New-M365DSCConfigurationToMarkdown -ParsedContent $parsedContent -OutputPath $OutputPath -TemplateName $templateName + 'Excel' + { + New-M365DSCConfigurationToExcel -ParsedContent $parsedContent -OutputPath $OutputPath + } + 'HTML' + { + $template = Get-Item $ConfigurationPath + $templateName = $Template.Name.Split('.')[0] + New-M365DSCConfigurationToHTML -ParsedContent $parsedContent -OutputPath $OutputPath -TemplateName $templateName + } + 'JSON' + { + New-M365DSCConfigurationToJSON -ParsedContent $parsedContent -OutputPath $OutputPath + } + 'Markdown' + { + $template = Get-Item $ConfigurationPath + $templateName = $Template.Name.Split('.')[0] + New-M365DSCConfigurationToMarkdown -ParsedContent $parsedContent -OutputPath $OutputPath -TemplateName $templateName + } } } + else + { + throw "Parsed content was null." + } } <# @@ -630,7 +637,7 @@ function Compare-M365DSCConfigurations #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Event', 'Compare') - Add-M365DSCTelemetryEvent -Data $data + Add-M365DSCTelemetryEvent -Data $data -Type 'CompareConfigurations' #endregion } @@ -1360,7 +1367,7 @@ function New-M365DSCDeltaReport #region Telemetry $data = [System.Collections.Generic.Dictionary[[String], [String]]]::new() $data.Add('Event', 'DeltaReport') - Add-M365DSCTelemetryEvent -Data $data + Add-M365DSCTelemetryEvent -Data $data -Type 'CompareConfigurations' #endregion # Excluding authentication properties by default. diff --git a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 index f7f155f0ae..dda43e2796 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCTelemetryEngine.psm1 @@ -229,7 +229,7 @@ function Add-M365DSCTelemetryEvent $Data.Add('LCMState', $LCMInfo.LCMState) $Data.Add('LCMStateDetail', $LCMInfo.LCMStateDetail) - if ([System.String]::IsNullOrEMpty($Type)) + if ([System.String]::IsNullOrEmpty($Type)) { if ($Global:M365DSCExportInProgress) { diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index 349b2e6dc1..1dca1435e2 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1412,7 +1412,7 @@ function Confirm-M365DSCDependencies [CmdletBinding()] param() - if (-not $Script:M365DSCDependenciesValidated) + if (-not $Script:M365DSCDependenciesValidated -and ($null -eq $Global:M365DSCSkipDependenciesValidation -or -not $Global:M365DSCSkipDependenciesValidation)) { Write-Verbose -Message 'Dependencies were not already validated.' From 5890473c4e4cb9413a14a755f618b7af4ef7fa99 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 21 Feb 2024 17:03:51 -0500 Subject: [PATCH 169/171] FIxes --- .../MSFT_AADApplication/MSFT_AADApplication.psm1 | 3 ++- .../MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof | 2 +- .../MSFT_EXOTransportRule/MSFT_EXOTransportRule.psm1 | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 index a6239345d7..290621c0ba 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_AADApplication/MSFT_AADApplication.psm1 @@ -148,7 +148,7 @@ function Get-TargetResource } if ($null -ne $AADApp -and $AADApp.Count -gt 1) { - Throw "Multiple AAD Apps with the Displayname $($DisplayName) exist in the tenant. These apps will not be exported." + Throw "Multiple AAD Apps with the Displayname $($DisplayName) exist in the tenant." } elseif ($null -eq $AADApp) { @@ -940,6 +940,7 @@ function Export-TargetResource Write-Host "`r`n $($Global:M365DSCEmojiYellowCircle)" -NoNewline Write-Host " Multiple app instances wth name {$($AADApp.DisplayName)} were found. We will skip exporting these instances." } + $i++ } } return $dscContent.ToString() diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof index b64646139d..794e83955f 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOMailboxPlan/MSFT_EXOMailboxPlan.schema.mof @@ -2,7 +2,7 @@ class MSFT_EXOMailboxPlan : OMI_BaseResource { [Key, Description("The Identity parameter specifies the Mailbox Plan that you want to modify.")] String Identity; - [Key, Description("The display name of the mailbox plan.")] String DisplayName; + [Write, Description("The display name of the mailbox plan.")] String DisplayName; [Write, Description("MailboxPlans cannot be created/removed in O365. This must be set to 'Present'"), ValueMap{"Present"}, Values{"Present"}] String Ensure; [Write, Description("The IssueWarningQuota parameter specifies the warning threshold for the size of the mailboxes that are created or enabled using the mailbox plan.")] String IssueWarningQuota; [Write, Description("The MaxReceiveSize parameter specifies the maximum size of a message that can be sent to the mailbox.")] String MaxReceiveSize; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTransportRule/MSFT_EXOTransportRule.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTransportRule/MSFT_EXOTransportRule.psm1 index 726c860b29..67ee277119 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTransportRule/MSFT_EXOTransportRule.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTransportRule/MSFT_EXOTransportRule.psm1 @@ -761,10 +761,7 @@ function Get-TargetResource Add-M365DSCTelemetryEvent -Data $data #endregion - - $AllTransportRules = Get-TransportRule - - $TransportRule = $AllTransportRules | Where-Object -FilterScript { $_.Name -eq $Name } + $TransportRule = Get-TransportRule -Identity $Name -ErrorAction 'SilentlyContinue' if ($null -eq $TransportRule) { From b58ba7b8aadcad3881f371daedaf1682c6fbe7a5 Mon Sep 17 00:00:00 2001 From: Nik Charlebois Date: Wed, 21 Feb 2024 18:27:20 -0500 Subject: [PATCH 170/171] Fixes Unit Tests --- ...oft365DSC.EXOAuthenticationPolicyAssignment.Tests.ps1 | 1 + ...Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 | 1 + .../Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 | 6 ++++++ .../Microsoft365DSC.EXOGroupSettings.Tests.ps1 | 1 + .../Microsoft365DSC.EXOTransportRule.Tests.ps1 | 9 +-------- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicyAssignment.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicyAssignment.Tests.ps1 index 85222c7b1e..315d8d4d32 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicyAssignment.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAuthenticationPolicyAssignment.Tests.ps1 @@ -154,6 +154,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { @{ Name = 'John.Smith' AuthenticationPolicy = 'Test Policy' + UserPrincipalName = 'john.smith@contoso.com' } ) } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 index 082ebc201b..91d6e7b7a9 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityAddressSpace.Tests.ps1 @@ -156,6 +156,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $testParams = @{ Ensure = 'Absent' Credential = $Credential + ForestName = 'contoso.com' Identity = 'TestAvailabilityAddressSpace' } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 index 15281ce041..9d5571a6c9 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOAvailabilityConfig.Tests.ps1 @@ -135,6 +135,12 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { $AvailabilityConfig = @{ OrgWideAccount = 'johndoe' + + } + Mock -CommandName Get-User -MockWith { + return @{ + UserPrincipalName = 'john.smith@contoso.com' + } } Mock -CommandName Get-AvailabilityConfig -MockWith { return $AvailabilityConfig diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOGroupSettings.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOGroupSettings.Tests.ps1 index 1ae3275f3b..e47722dd4a 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOGroupSettings.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOGroupSettings.Tests.ps1 @@ -202,6 +202,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Mock -CommandName Get-UnifiedGroup -MockWith { return @{ DisplayName = "Test Group"; + Id = '12345-12345-12345-12345-12345' AccessType = "Public"; AlwaysSubscribeMembersToCalendarEvents = $False; AuditLogAgeLimit = "90.00:00:00"; diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTransportRule.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTransportRule.Tests.ps1 index 7ad264db82..7fc53f7ee3 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTransportRule.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTransportRule.Tests.ps1 @@ -57,14 +57,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-TransportRule -MockWith { - return @{ - Name = 'Contoso Different Transport Rule' - BetweenMemberOf1 = 'Sales Department' - BetweenMemberOf2 = 'Marketing Department' - ExceptIfSubjectContainsWords = 'Press Release' - RejectMessageReasonText = 'Messages sent between the Sales and Marketing departments are strictly prohibited.' - FreeBusyAccessLevel = 'AvailabilityOnly' - } + return $null } } From ce8d12e8c63bf80e0265b428c2d4ac63486dbd33 Mon Sep 17 00:00:00 2001 From: NikCharlebois Date: Thu, 22 Feb 2024 12:00:15 +0000 Subject: [PATCH 171/171] Updated Resources and Cmdlet documentation pages --- docs/docs/resources/exchange/EXOActiveSyncDeviceAccessRule.md | 1 + docs/docs/resources/exchange/EXOCASMailboxPlan.md | 1 + docs/docs/resources/exchange/EXOGroupSettings.md | 1 + docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md | 1 + docs/docs/resources/exchange/EXOMailboxPlan.md | 1 + docs/docs/resources/exchange/EXOPlace.md | 1 + docs/docs/resources/exchange/EXOSharedMailbox.md | 1 + 7 files changed, 7 insertions(+) diff --git a/docs/docs/resources/exchange/EXOActiveSyncDeviceAccessRule.md b/docs/docs/resources/exchange/EXOActiveSyncDeviceAccessRule.md index 89fa8cecdf..de9726e532 100644 --- a/docs/docs/resources/exchange/EXOActiveSyncDeviceAccessRule.md +++ b/docs/docs/resources/exchange/EXOActiveSyncDeviceAccessRule.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the identity of the device access rule. | | +| **GUID** | Write | String | Unique Identifier. Read-Only | | | **AccessLevel** | Write | String | The AccessLevel parameter specifies whether the devices are allowed, blocked or quarantined. | `Allow`, `Block`, `Quarantine` | | **Characteristic** | Write | String | The Characteristic parameter specifies the device characteristic or category that's used by the rule. | `DeviceModel`, `DeviceType`, `DeviceOS`, `UserAgent`, `XMSWLHeader` | | **QueryString** | Write | String | The QueryString parameter specifies the device identifier that's used by the rule. This parameter uses a text value that's used with Characteristic parameter value to define the device. | | diff --git a/docs/docs/resources/exchange/EXOCASMailboxPlan.md b/docs/docs/resources/exchange/EXOCASMailboxPlan.md index 44b9628e75..ace2eb2262 100644 --- a/docs/docs/resources/exchange/EXOCASMailboxPlan.md +++ b/docs/docs/resources/exchange/EXOCASMailboxPlan.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the CAS Mailbox Plan that you want to modify. | | +| **DisplayName** | Write | String | The display name of the CAS Mailbox Plan. | | | **Ensure** | Write | String | CASMailboxPlans cannot be created/removed in O365. This must be set to 'Present' | `Present` | | **ActiveSyncEnabled** | Write | Boolean | The ActiveSyncEnabled parameter enables or disables access to the mailbox by using Exchange Active Sync. Default is $true. | | | **ImapEnabled** | Write | Boolean | The ImapEnabled parameter enables or disables access to the mailbox by using IMAP4 clients. The default value is $true for all CAS mailbox plans except ExchangeOnlineDeskless which is $false by default. | | diff --git a/docs/docs/resources/exchange/EXOGroupSettings.md b/docs/docs/resources/exchange/EXOGroupSettings.md index f9ddf2d3bd..0f94726fc3 100644 --- a/docs/docs/resources/exchange/EXOGroupSettings.md +++ b/docs/docs/resources/exchange/EXOGroupSettings.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **DisplayName** | Key | String | The DisplayName parameter specifies the name of the Microsoft 365 Group. The display name is visible in the Exchange admin center, address lists, and Outlook. The maximum length is 64 characters. | | +| **Id** | Write | String | The unique Id of the group | | | **AcceptMessagesOnlyFromSendersOrMembers** | Write | StringArray[] | The AcceptMessagesOnlyFromSendersOrMembers parameter specifies who is allowed to send messages to this recipient. Messages from other senders are rejected. | | | **AccessType** | Write | String | Private | `Public`, `Private` | | **AlwaysSubscribeMembersToCalendarEvents** | Write | Boolean | The AlwaysSubscribeMembersToCalendarEvents switch controls the default subscription settings of new members that are added to the Microsoft 365 Group. Changing this setting doesn't affect existing group members. | | diff --git a/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md b/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md index d976f09127..b6ede357dc 100644 --- a/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md +++ b/docs/docs/resources/exchange/EXOMailboxAutoReplyConfiguration.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the mailbox that you want to modify. You can use any value that uniquely identifies the mailbox. | | +| **Owner** | Write | String | User Principal Name of the mailbox owner | | | **AutoDeclineFutureRequestsWhenOOF** | Write | Boolean | The AutoDeclineFutureRequestsWhenOOF parameter specifies whether to automatically decline new meeting requests that are sent to the mailbox during the scheduled time period when Automatic Replies are being sent. | | | **AutoReplyState** | Write | String | The AutoReplyState parameter specifies whether the mailbox is enabled for Automatic Replies. Valid values are: Enabled, Disabled, Scheduled | `Enabled`, `Disabled`, `Scheduled` | | **CreateOOFEvent** | Write | Boolean | The CreateOOFEvent parameter specifies whether to create a calendar event that corresponds to the scheduled time period when Automatic Replies are being sent for the mailbox. | | diff --git a/docs/docs/resources/exchange/EXOMailboxPlan.md b/docs/docs/resources/exchange/EXOMailboxPlan.md index a71b4df323..219460e4a2 100644 --- a/docs/docs/resources/exchange/EXOMailboxPlan.md +++ b/docs/docs/resources/exchange/EXOMailboxPlan.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the Mailbox Plan that you want to modify. | | +| **DisplayName** | Write | String | The display name of the mailbox plan. | | | **Ensure** | Write | String | MailboxPlans cannot be created/removed in O365. This must be set to 'Present' | `Present` | | **IssueWarningQuota** | Write | String | The IssueWarningQuota parameter specifies the warning threshold for the size of the mailboxes that are created or enabled using the mailbox plan. | | | **MaxReceiveSize** | Write | String | The MaxReceiveSize parameter specifies the maximum size of a message that can be sent to the mailbox. | | diff --git a/docs/docs/resources/exchange/EXOPlace.md b/docs/docs/resources/exchange/EXOPlace.md index 23742979fc..f0c2a12308 100644 --- a/docs/docs/resources/exchange/EXOPlace.md +++ b/docs/docs/resources/exchange/EXOPlace.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Identity** | Key | String | The Identity parameter specifies the room mailbox that you want to modify. You can use any value that uniquely identifies the room. | | +| **DisplayName** | Write | String | The display name of the place. | | | **AudioDeviceName** | Write | String | The AudioDeviceName parameter specifies the name of the audio device in the room. If the value contains spaces, enclose the value in quotation marks. | | | **Building** | Write | String | The Building parameter specifies the building name or building number that the room is in. If the value contains spaces, enclose the value in quotation marks. | | | **Capacity** | Write | UInt32 | The Capacity parameter specifies the capacity of the room. A valid value is an integer. | | diff --git a/docs/docs/resources/exchange/EXOSharedMailbox.md b/docs/docs/resources/exchange/EXOSharedMailbox.md index ff1c50ddc9..ac9a5df2d6 100644 --- a/docs/docs/resources/exchange/EXOSharedMailbox.md +++ b/docs/docs/resources/exchange/EXOSharedMailbox.md @@ -5,6 +5,7 @@ | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **DisplayName** | Key | String | The display name of the Shared Mailbox | | +| **Identity** | Write | String | The unique identifier of the Shared Mailbox | | | **PrimarySMTPAddress** | Write | String | The primary email address of the Shared Mailbox | | | **Alias** | Write | String | The alias of the Shared Mailbox | | | **EmailAddresses** | Write | StringArray[] | The EmailAddresses parameter specifies all the email addresses (proxy addresses) for the Shared Mailbox | |