diff --git a/CHANGELOG.md b/CHANGELOG.md index e5b1ed3c55..4bc77153c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,10 @@ 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)] @@ -81,6 +85,7 @@ * Validate string set on parameter MobileDialerPreference * DEPENDENCIES * Updated Microsoft.Graph dependencies to version 2.12.0. + * Updated MicrosoftTeams dependencies to version 5.9.0. # 1.24.117.1 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOApplicationAccessPolicy/MSFT_EXOApplicationAccessPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOApplicationAccessPolicy/MSFT_EXOApplicationAccessPolicy.psm1 index abde1b37c6..a6c009db0d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOApplicationAccessPolicy/MSFT_EXOApplicationAccessPolicy.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOApplicationAccessPolicy/MSFT_EXOApplicationAccessPolicy.psm1 @@ -89,20 +89,45 @@ function Get-TargetResource try { + $ApplicationAccessPolicy = $null try { - $AllApplicationAccessPolicies = Get-ApplicationAccessPolicy -ErrorAction Stop + [Array]$ApplicationAccessPolicy = Get-ApplicationAccessPolicy -Identity $Identity -ErrorAction Stop + Write-Verbose -Message "Found policy by Identity {$Identity}" } catch { - if ($_.Exception -like "The operation couldn't be performed because object*") + Write-Verbose -Message "Could not find policy by Identity {$Identity}" + } + + $ScopeIdentityValue = $null + if ($null -eq $ApplicationAccessPolicy) + { + $scopeIdentityGroup = $null + try { - Write-Verbose 'Could not obtain Application Access Policies for Tenant' - return $nullReturn + $scopeIdentityGroup = Get-Group -Identity $PolicyScopeGroupId -ErrorAction Stop + } + catch + { + Write-Verbose -Message "Could not find Group with Identity {$PolicyScopeGroupId}" + } + + if ($null -ne $scopeIdentityGroup) + { + $ScopeIdentityValue = $scopeIdentityGroup.WindowsEmailAddress + $ApplicationAccessPolicy = Get-ApplicationAccessPolicy | Where-Object -FilterScript { $AppID -eq $_.AppId -and $_.ScopeIdentity -eq $scopeIdentityGroup } } - } - $ApplicationAccessPolicy = $AllApplicationAccessPolicies | Where-Object -FilterScript { $_.Identity -eq $Identity } + if ($null -ne $ApplicationAccessPolicy) + { + Write-Verbose -Message "Found Application Access Policy by Scope {$PolicyScopeGroupId}" + } + } + else + { + $ScopeIdentityValue = $ApplicationAccessPolicy.ScopeIdentity + } if ($null -eq $ApplicationAccessPolicy) { @@ -111,11 +136,12 @@ function Get-TargetResource } else { + $ApplicationAccessPolicy = $ApplicationAccessPolicy[0] $result = @{ Identity = $ApplicationAccessPolicy.Identity AccessRight = $ApplicationAccessPolicy.AccessRight AppID = $ApplicationAccessPolicy.AppID - PolicyScopeGroupId = $ApplicationAccessPolicy.ScopeIdentity + PolicyScopeGroupId = $ScopeIdentityValue Description = $ApplicationAccessPolicy.Description Ensure = 'Present' Credential = $Credential @@ -127,7 +153,7 @@ function Get-TargetResource TenantId = $TenantId } - Write-Verbose -Message "Found Application Access Policy $($Identity)" + Write-Verbose -Message "Found Application Access Policy {$($Identity)}" return $result } } @@ -231,7 +257,7 @@ function Set-TargetResource } $SetApplicationAccessPolicyParams = @{ - Identity = $Identity + Identity = $currentApplicationAccessPolicyConfig.Identity Description = $Description Confirm = $false } @@ -253,16 +279,18 @@ function Set-TargetResource # CASE: Application Access Policy exists and it should, but Description attribute has different values than desired (Set-ApplicationAccessPolicy is only able to change description attribute) elseif ($Ensure -eq 'Present' -and $currentApplicationAccessPolicyConfig.Ensure -eq 'Present' -and $currentApplicationAccessPolicyConfig.Description -ne $Description) { - Write-Verbose -Message "Application Access Policy '$($Identity)' already exists, but needs updating." - Write-Verbose -Message "Setting Application Access Policy $($Identity) with values: $(Convert-M365DscHashtableToString -Hashtable $SetApplicationAccessPolicyParams)" + Write-Verbose -Message "Application Access Policy '$($currentApplicationAccessPolicyConfig.Identity)' already exists, but needs updating." + Write-Verbose -Message "Setting Application Access Policy $($currentApplicationAccessPolicyConfig.Identity) with values: $(Convert-M365DscHashtableToString -Hashtable $SetApplicationAccessPolicyParams)" Set-ApplicationAccessPolicy @SetApplicationAccessPolicyParams } # CASE: Application Access Policy exists and it should, but has different values than the desired one # Set-ApplicationAccessPolicy is only able to change description attribute, therefore re-create policy elseif ($Ensure -eq 'Present' -and $currentApplicationAccessPolicyConfig.Ensure -eq 'Present' -and $currentApplicationAccessPolicyConfig.Description -eq $Description) { - Write-Verbose -Message "Re-create Application Access Policy '$($Identity)'" - Remove-ApplicationAccessPolicy -Identity $Identity -Confirm:$false + Write-Verbose -Message "Re-create Application Access Policy '$($currentApplicationAccessPolicyConfig.Identity)'" + Remove-ApplicationAccessPolicy -Identity $currentApplicationAccessPolicyConfig.Identity -Confirm:$false + Write-Verbose -Message "Removing existing policy was successful" + Write-Verbose -Message "Creating new instance with parameters: $(Convert-M365DscHashtableToString -Hashtable $NewApplicationAccessPolicyParams)" New-ApplicationAccessPolicy @NewApplicationAccessPolicyParams } } @@ -354,6 +382,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) ` @@ -487,4 +516,3 @@ function Export-TargetResource } Export-ModuleMember -Function *-TargetResource - diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 index 620b2c6ee2..6b03e06a7d 100644 --- a/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXODataClassification/MSFT_EXODataClassification.psm1 @@ -242,19 +242,9 @@ function Set-TargetResource $DataClassificationParams.Remove('CertificatePassword') | Out-Null $DataClassificationParams.Remove('ManagedIdentity') | Out-Null - if (('Present' -eq $Ensure ) -and ($null -eq $DataClassification)) { - Write-Verbose -Message "Creating Data classification policy $($Identity)." - $DataClassificationParams.Remove('Identity') | Out-Null - $DataClassificationParams.Remove('IsDefault') | Out-Null - if (-Not [String]::IsNullOrEmpty($DataClassificationParams.Locale)) - { - $DataClassificationParams.Locale = New-Object system.globalization.cultureinfo($DataClassificationParams.Locale) - } - - New-DataClassification @DataClassificationParams - Write-Verbose -Message 'Data classification policy created successfully.' + Write-Verbose -Message "Data Classification in Exchange Online are now deprecated in favor of Sensitive Information Types in Security and Compliance." } elseif (('Present' -eq $Ensure ) -and ($Null -ne $DataClassification)) { diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index 92ac5bc2ff..ed504505f0 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -82,7 +82,7 @@ }, @{ ModuleName = 'MicrosoftTeams' - RequiredVersion = '5.8.0' + RequiredVersion = '5.9.0' }, @{ ModuleName = "MSCloudLoginAssistant" diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/1-Create.ps1 index c88c0ab014..b7008e86fb 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/1-Create.ps1 @@ -13,14 +13,15 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOApplicationAccessPolicy 'ConfigureApplicationAccessPolicy' { - Identity = "Global" + Identity = "Integration Policy" AccessRight = "DenyAccess" - AppID = @("3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5", "6ac794ca-2697-4137-8754-d2a78ae47d93") - PolicyScopeGroupId = "Engineering Staff" + AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' + PolicyScopeGroupId = "IntegrationMailEnabled@$Domain" Description = "Engineering Group Policy" Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/2-Update.ps1 index 54b710aa43..f961e93505 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/2-Update.ps1 @@ -13,14 +13,15 @@ Configuration Example ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOApplicationAccessPolicy 'ConfigureApplicationAccessPolicy' { - Identity = "Global" + Identity = "Integration Policy" AccessRight = "DenyAccess" - AppID = @("3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5", "6ac794ca-2697-4137-8754-d2a78ae47d93") - PolicyScopeGroupId = "Engineering Staff" + AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' + PolicyScopeGroupId = "IntegrationMailEnabled@$Domain" Description = "Engineering Group Policy Updated" # Updated Property Ensure = "Present" Credential = $Credscredential diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/3-Remove.ps1 index de77a3afce..cc0936181d 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOApplicationAccessPolicy/3-Remove.ps1 @@ -17,7 +17,8 @@ Configuration Example { EXOApplicationAccessPolicy 'ConfigureApplicationAccessPolicy' { - Identity = "Global" + Identity = "Integration Policy" + AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' Ensure = "Absent" Credential = $Credscredential } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 index 1970482fa3..0fb2f2f613 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/1-Create.ps1 @@ -3,7 +3,7 @@ Configuration Example param( [Parameter(Mandatory = $true)] [PSCredential] - $EXOAdmin + $Credscredential ) Import-DscResource -ModuleName Microsoft365DSC @@ -14,7 +14,7 @@ Configuration Example UserName = "AdeleV" AuthenticationPolicyName = "Block Basic Auth" Ensure = "Present" - Credential = $EXOAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 index fca14ac182..878bf3ebe1 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/2-Update.ps1 @@ -3,18 +3,19 @@ Configuration Example param( [Parameter(Mandatory = $true)] [PSCredential] - $EXOAdmin + $Credscredential ) Import-DscResource -ModuleName Microsoft365DSC + $Domain = $Credscredential.Username.Split('@')[1] node localhost { EXOAuthenticationPolicyAssignment 'ConfigureAuthenticationPolicyAssignment' { UserName = "AdeleV" - AuthenticationPolicyName = "Test Policy" + AuthenticationPolicyName = "Test Policy" # Updaqted Property Ensure = "Present" - Credential = $EXOAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 index aa739f5c3e..becf7194b5 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOAuthenticationPolicyAssignment/3-Remove.ps1 @@ -3,7 +3,7 @@ Configuration Example param( [Parameter(Mandatory = $true)] [PSCredential] - $EXOAdmin + $Credscredential ) Import-DscResource -ModuleName Microsoft365DSC @@ -14,7 +14,7 @@ Configuration Example UserName = "AdeleV" AuthenticationPolicyName = "Test Policy" Ensure = "Absent" - Credential = $EXOAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/1-Create.ps1 index 796c7e53c4..5eb5199ae4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/1-Create.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/1-Create.ps1 @@ -30,7 +30,7 @@ Configuration Example ExceptAnyOfClientIPAddressesOrRanges = @() AnyOfClientIPAddressesOrRanges = @() Ensure = "Present" - Credential = $GlobalAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/2-Update.ps1 index 54c4502dde..023a903f60 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/2-Update.ps1 @@ -30,7 +30,7 @@ Configuration Example ExceptAnyOfClientIPAddressesOrRanges = @() AnyOfClientIPAddressesOrRanges = @() Ensure = "Present" - Credential = $GlobalAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/3-Remove.ps1 index 4b4fbfeaf9..42f5cf21c7 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/3-Remove.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOClientAccessRule/3-Remove.ps1 @@ -19,7 +19,7 @@ Configuration Example Action = "AllowAccess" Identity = "Always Allow Remote PowerShell" Ensure = "Absent" - Credential = $GlobalAdmin + Credential = $Credscredential } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/1-Create.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/1-Create.ps1 deleted file mode 100644 index 406907f169..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/1-Create.ps1 +++ /dev/null @@ -1,28 +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 - { - EXODataClassification 'ConfigureDataClassification' - { - Identity = 'Contoso Confidential' - Name = 'Contoso Confidentiel' - Description = 'Ce message contient des informations confidentielles.' - Locale = 'fr' - IsDefault = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/2-Update.ps1 index 1f4d62384e..c13499914c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/2-Update.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/2-Update.ps1 @@ -16,13 +16,13 @@ Configuration Example { EXODataClassification 'ConfigureDataClassification' { - Identity = 'Contoso Confidential' - Name = 'Contoso Confidentiel' - Description = 'Ce message contient des informations confidentielles. Updated' # Updated Property - Locale = 'fr' - IsDefault = $true - Ensure = "Present" - Credential = $Credscredential + 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 } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/3-Remove.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/3-Remove.ps1 deleted file mode 100644 index 1f4d62384e..0000000000 --- a/Modules/Microsoft365DSC/Examples/Resources/EXODataClassification/3-Remove.ps1 +++ /dev/null @@ -1,28 +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 - { - EXODataClassification 'ConfigureDataClassification' - { - Identity = 'Contoso Confidential' - Name = 'Contoso Confidentiel' - Description = 'Ce message contient des informations confidentielles. Updated' # Updated Property - Locale = 'fr' - IsDefault = $true - Ensure = "Present" - Credential = $Credscredential - } - } -} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOApplicationAccessPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOApplicationAccessPolicy.Tests.ps1 index 8d7b010ff8..f16ed46c56 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOApplicationAccessPolicy.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOApplicationAccessPolicy.Tests.ps1 @@ -21,6 +21,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope BeforeAll { + $Script:ExportMode = $false $secpasswd = ConvertTo-SecureString 'test@password1' -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) @@ -56,13 +57,7 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-ApplicationAccessPolicy -MockWith { - return @{ - Identity = 'DifferentApplicationAccessPolicy1' - AccessRight = 'DenyAccess' - AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' - ScopeIdentity = 'Engineering Staff' - Description = 'Engineering Group Policy' - } + return $null } Mock -CommandName Set-ApplicationAccessPolicy -MockWith { @@ -101,13 +96,13 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { } Mock -CommandName Get-ApplicationAccessPolicy -MockWith { - return @{ + return @(@{ Identity = 'ApplicationAccessPolicy1' AccessRight = 'DenyAccess' AppID = '3dbc2ae1-7198-45ed-9f9f-d86ba3ec35b5' ScopeIdentity = 'Engineering Staff' Description = 'Engineering Group Policy' - } + }) } } diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 index 38d9729b8f..e2c9b7fe7d 100644 --- a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXODataClassification.Tests.ps1 @@ -70,7 +70,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call the New- cmdlet' { Set-TargetResource @testParams - Should -Invoke -CommandName 'New-DataClassification' -Exactly 1 } } @@ -107,7 +106,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should set Call into the Set-DataClassification command exactly once' { Set-TargetResource @testParams - Should -Invoke -CommandName 'Set-DataClassification' -Exactly 1 } } @@ -144,7 +142,6 @@ Describe -Name $Global:DscHelper.DescribeHeader -Fixture { It 'Should call into the Remove-DataClassification cmdlet once' { Set-TargetResource @testParams - Should -Invoke -CommandName 'Remove-DataClassification' -Exactly 1 } }