diff --git a/CHANGELOG.md b/CHANGELOG.md index 1435c713f8..ebacfe81c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ reading and troubleshooting * AADRoleManagementPolicyRule * Added the logic to handle filters in the Export logic flow. +* EXOTeamsProtectionPolicy + * Initial release + FIXES [#5296](https://github.com/microsoft/Microsoft365DSC/issues/5296) * EXOTransportRule * Fixed conditional logic for creation and update. * IntuneTrustedRootCertificateIOS diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.psm1 new file mode 100644 index 0000000000..02b6d344dc --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.psm1 @@ -0,0 +1,428 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.String] + $AdminDisplayName, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + Write-Verbose -Message "Getting configuration of Teams Protection Policy" + $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 = @{ + IsSingleInstance = 'Yes' + AdminDisplayName = $null + HighConfidencePhishQuarantineTag = $null + MalwareQuarantineTag = $null + ZapEnabled = $null + } + + try + { + $ProtectionPolicy = Get-TeamsProtectionPolicy + + if ($null -eq $ProtectionPolicy) + { + Write-Verbose -Message "Teams Protection Policy does not exist." + return $nullReturn + } + else + { + $result = @{ + IsSingleInstance = 'Yes' + AdminDisplayName = $ProtectionPolicy.AdminDisplayName + HighConfidencePhishQuarantineTag = $ProtectionPolicy.HighConfidencePhishQuarantineTag + MalwareQuarantineTag = $ProtectionPolicy.MalwareQuarantineTag + ZapEnabled = $ProtectionPolicy.ZapEnabled + Credential = $Credential + ApplicationId = $ApplicationId + CertificateThumbprint = $CertificateThumbprint + CertificatePath = $CertificatePath + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + TenantId = $TenantId + AccessTokens = $AccessTokens + } + + Write-Verbose -Message "Found ProtectionPolicy" + Write-Verbose -Message "Get-TargetResource Result: `n $(Convert-M365DscHashtableToString -Hashtable $result)" + 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(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.String] + $AdminDisplayName, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + Write-Verbose -Message "Setting configuration of Teams Protection Policy" + + $ConnectionMode = New-M365DSCConnection -Workload 'ExchangeOnline' ` + -InboundParameters $PSBoundParameters + + $currentValues = Get-TargetResource @PSBoundParameters + + if ($null -eq $currentValues.AdminDisplayName -and ` + $null -eq $currentValues.HighConfidencePhishQuarantineTag -and ` + $null -eq $currentValues.MalwareQuarantineTag -and ` + $null -eq $currentValues.ZapEnabled) + { + Write-Verbose -Message 'Teams Protection Policy does not exist, creating new policy' + New-TeamsProtectionPolicy -Name 'Teams Protection Policy' + } + + $params = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + $params.Add('Identity', 'Teams Protection Policy') + $params.Remove('IsSingleInstance') + + Set-TeamsProtectionPolicy @params +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [ValidateSet('Yes')] + [System.String] + $IsSingleInstance, + + [Parameter()] + [System.String] + $AdminDisplayName, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [ValidateSet('AdminOnlyAccessPolicy', 'DefaultFullAccessPolicy', 'DefaultFullAccessWithNotificationPolicy')] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [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, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName -replace 'MSFT_', '' + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + Write-Verbose -Message 'Testing configuration of Teams Protection Policy' + + $CurrentValues = Get-TargetResource @PSBoundParameters + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $PSBoundParameters)" + + $ValuesToCheck = $PSBoundParameters + + $TestResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $($TestResult)" + + return $TestResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [System.String] + $CertificatePath, + + [Parameter()] + [System.Management.Automation.PSCredential] + $CertificatePassword, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + $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 + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $dscContent = '' + + [array]$teamsProtectionPolicy = Get-TeamsProtectionPolicy + if ($null -ne $teamsProtectionPolicy) + { + $Params = @{ + IsSingleInstance = 'Yes' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + CertificatePassword = $CertificatePassword + Managedidentity = $ManagedIdentity.IsPresent + CertificatePath = $CertificatePath + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + } + + Write-Host $Global:M365DSCEmojiGreenCheckMark + + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} +Export-ModuleMember -Function *-TargetResource + diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.schema.mof new file mode 100644 index 0000000000..c6c4d1c24f --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/MSFT_EXOTeamsProtectionPolicy.schema.mof @@ -0,0 +1,18 @@ + +[ClassVersion("1.0.0.0"), FriendlyName("EXOTeamsProtectionPolicy")] +class MSFT_EXOTeamsProtectionPolicy : OMI_BaseResource +{ + [Key, Description("Only valid value is 'Yes'."), ValueMap{"Yes"}, Values{"Yes"}] String IsSingleInstance; + [Write, Description("The AdminDisplayName parameter specifies a description for the policy.")] String AdminDisplayName; + [Write, Description("The HighConfidencePhishQuarantineTag parameter specifies the quarantine policy that's used for messages that are quarantined as high confidence phishing by ZAP for Teams."), ValueMap{"AdminOnlyAccessPolicy","DefaultFullAccessPolicy","DefaultFullAccessWithNotificationPolicy"}, Values{"AdminOnlyAccessPolicy","DefaultFullAccessPolicy","DefaultFullAccessWithNotificationPolicy"}] String HighConfidencePhishQuarantineTag; + [Write, Description("The MalwareQuarantineTag parameter specifies the quarantine policy that's used for messages that are quarantined as malware by ZAP for Teams."), ValueMap{"AdminOnlyAccessPolicy","DefaultFullAccessPolicy","DefaultFullAccessWithNotificationPolicy"}, Values{"AdminOnlyAccessPolicy","DefaultFullAccessPolicy","DefaultFullAccessWithNotificationPolicy"}] String MalwareQuarantineTag; + [Write, Description("The ZapEnabled parameter specifies whether to enable zero-hour auto purge (ZAP) for malware and high confidence phishing messages in Teams messages.")] Boolean ZapEnabled; + [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; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/readme.md new file mode 100644 index 0000000000..45288c36d0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/readme.md @@ -0,0 +1,5 @@ +# EXOTeamsProtectionPolicy + +## Description + +Create or modify a TeamsProtectionPolicy in your cloud-based organization. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/settings.json new file mode 100644 index 0000000000..81528a1617 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_EXOTeamsProtectionPolicy/settings.json @@ -0,0 +1,34 @@ +{ + "resourceName": "EXOTeamsProtectionPolicy", + "description": "", + "roles": { + "read": [ + "Security Reader" + ], + "update": [ + "Security Administrator" + ] + }, + "permissions": { + "graph": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [], + "update": [] + } + }, + "exchange": { + "requiredroles": [ + "Compliance Management", + "Delegated Setup", + "Hygiene Management", + "Organization Management", + "View-Only Organization Management" + ], + "requiredrolegroups": "Organization Management" + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/EXOTeamsProtectionPolicy/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/EXOTeamsProtectionPolicy/2-Update.ps1 new file mode 100644 index 0000000000..cf5c6abffa --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/EXOTeamsProtectionPolicy/2-Update.ps1 @@ -0,0 +1,39 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + + Import-DscResource -ModuleName Microsoft365DSC + + node localhost + { + EXOTeamsProtectionPolicy 'EXOTeamsProtectionPolicy' + { + IsSingleInstance = 'Yes' + AdminDisplayName = 'Contoso Administrator' + HighConfidencePhishQuarantineTag = 'DefaultFullAccessPolicy' + MalwareQuarantineTag = 'AdminOnlyAccessPolicy' + ZapEnabled = $true + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + } + } +} diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCCaseHoldPolicy/1-AddingNewCaseHoldPolicy.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCCaseHoldPolicy/1-AddingNewCaseHoldPolicy.ps1 index 62fd2b4ce1..f7be800862 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCCaseHoldPolicy/1-AddingNewCaseHoldPolicy.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCCaseHoldPolicy/1-AddingNewCaseHoldPolicy.ps1 @@ -5,10 +5,19 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) Import-DscResource -ModuleName Microsoft365DSC @@ -16,14 +25,16 @@ Configuration Example { SCCaseHoldPolicy 'CaseHoldPolicy' { - Case = "Test Case" - ExchangeLocation = "DemoGroup@contoso.onmicrosoft.com" - Name = "Demo Hold" - PublicFolderLocation = "All" - Comment = "This is a demo" - Enabled = $True - Ensure = "Present" - Credential = $Credscredential + Case = 'Test Case' + ExchangeLocation = 'DemoGroup@contoso.onmicrosoft.com' + Name = 'Demo Hold' + PublicFolderLocation = 'All' + Comment = 'This is a demo' + Enabled = $True + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCSupervisoryReviewRule/1-AddingNewSupervisoryReviewRule.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCSupervisoryReviewRule/1-AddingNewSupervisoryReviewRule.ps1 index dfa50fdd60..3cf4a2fe32 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCSupervisoryReviewRule/1-AddingNewSupervisoryReviewRule.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCSupervisoryReviewRule/1-AddingNewSupervisoryReviewRule.ps1 @@ -5,23 +5,35 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC Node localhost { SCSupervisoryReviewRule 'SupervisoryReviewRule' { - Name = "DemoRule" - Condition = "(NOT(Reviewee:US Compliance))" - SamplingRate = 100 - Policy = 'TestPolicy' - Ensure = "Present" - Credential = $Credscredential + Name = 'DemoRule' + Condition = '(NOT(Reviewee:US Compliance))' + SamplingRate = 100 + Policy = 'TestPolicy' + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 index ead7b6c305..0837897aae 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/SCUnifiedAuditLogRetentionPolicy/1-CreateNewUnifiedAuditLogRetentionPolicy.ps1 @@ -5,22 +5,35 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credentials + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { SCUnifiedAuditLogRetentionPolicy 'Example' { - Credential = $Credentials; - Ensure = "Present"; - Name = "Test Policy"; - Priority = 1; - RetentionDuration = "SevenDays"; + Credential = $Credentials + Ensure = 'Present' + Name = 'Test Policy' + Priority = 1 + RetentionDuration = 'SevenDays' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsCallHoldPolicy/1-TeamsCallHoldPolicy-Example.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsCallHoldPolicy/1-TeamsCallHoldPolicy-Example.ps1 index 6af82a7e56..ba3768eab4 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsCallHoldPolicy/1-TeamsCallHoldPolicy-Example.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsCallHoldPolicy/1-TeamsCallHoldPolicy-Example.ps1 @@ -5,10 +5,19 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) Import-DscResource -ModuleName Microsoft365DSC @@ -16,9 +25,11 @@ Configuration Example { TeamsCallHoldPolicy 'Example' { - Credential = $Credscredential; - Ensure = "Present"; - Identity = "Global"; + Identity = 'Global' + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsChannel/1-CreateTeamsChannel.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsChannel/1-CreateTeamsChannel.ps1 index f5e7e31644..8bbd2e0b5c 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsChannel/1-CreateTeamsChannel.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsChannel/1-CreateTeamsChannel.ps1 @@ -5,23 +5,35 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { TeamsChannel 'ConfigureChannel' { - TeamName = "SuperSecretTeam" - DisplayName = "SP2013 Review teams group" - NewDisplayName = "SP2016 Review teams group" - Description = "SP2016 Code reviews for SPFX" - Ensure = "Present" - Credential = $Credscredential + TeamName = 'SuperSecretTeam' + DisplayName = 'SP2013 Review teams group' + NewDisplayName = 'SP2016 Review teams group' + Description = 'SP2016 Code reviews for SPFX' + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsChannelsPolicy/1-AddNewChannelsPolicy.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsChannelsPolicy/1-AddNewChannelsPolicy.ps1 index 9f2cb1a24e..a202f4c10e 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsChannelsPolicy/1-AddNewChannelsPolicy.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsChannelsPolicy/1-AddNewChannelsPolicy.ps1 @@ -6,9 +6,17 @@ Configuration Example { param ( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) Import-DscResource -ModuleName Microsoft365DSC @@ -26,7 +34,9 @@ Configuration Example AllowSharedChannelCreation = $True AllowUserToParticipateInExternalSharedChannel = $True Ensure = 'Present' - Credential = $Credscredential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsShiftsPolicy/1-TeamsShiftsPolicy-Example.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsShiftsPolicy/1-TeamsShiftsPolicy-Example.ps1 index 4edfab81b1..79947b0277 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsShiftsPolicy/1-TeamsShiftsPolicy-Example.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsShiftsPolicy/1-TeamsShiftsPolicy-Example.ps1 @@ -5,10 +5,19 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) Import-DscResource -ModuleName Microsoft365DSC @@ -16,16 +25,18 @@ Configuration Example { TeamsShiftsPolicy 'Example' { - AccessGracePeriodMinutes = 15; - AccessType = "UnrestrictedAccess_TeamsApp"; - Credential = $Credscredential; - EnableScheduleOwnerPermissions = $False; - EnableShiftPresence = $False; - Ensure = "Present"; - Identity = "Global"; - ShiftNoticeFrequency = "Never"; - ShiftNoticeMessageCustom = ""; - ShiftNoticeMessageType = "DefaultMessage"; + Identity = 'Global' + AccessGracePeriodMinutes = 15 + AccessType = 'UnrestrictedAccess_TeamsApp' + EnableScheduleOwnerPermissions = $False + EnableShiftPresence = $False + Ensure = 'Present' + ShiftNoticeFrequency = 'Never' + ShiftNoticeMessageCustom = '' + ShiftNoticeMessageType = 'DefaultMessage' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Examples/Resources/TeamsTeam/1-CreateNewTeam.ps1 b/Modules/Microsoft365DSC/Examples/Resources/TeamsTeam/1-CreateNewTeam.ps1 index af538b0418..9d2b9e2096 100644 --- a/Modules/Microsoft365DSC/Examples/Resources/TeamsTeam/1-CreateNewTeam.ps1 +++ b/Modules/Microsoft365DSC/Examples/Resources/TeamsTeam/1-CreateNewTeam.ps1 @@ -5,21 +5,31 @@ It is not meant to use as a production baseline. Configuration Example { - param( - [Parameter(Mandatory = $true)] - [PSCredential] - $Credscredential + param + ( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint ) + Import-DscResource -ModuleName Microsoft365DSC node localhost { TeamsTeam 'ConfigureTeam' { - DisplayName = "Sample3" - Description = "Sample" - Visibility = "Private" - MailNickName = "DSCTeam2" + DisplayName = 'Sample3' + Description = 'Sample' + Visibility = 'Private' + MailNickName = 'DSCTeam2' AllowUserEditMessages = $false AllowUserDeleteMessages = $false AllowOwnerDeleteMessages = $false @@ -31,13 +41,15 @@ Configuration Example AllowCreateUpdateRemoveTabs = $false AllowCreateUpdateRemoveConnectors = $false AllowGiphy = $True - GiphyContentRating = "strict" + GiphyContentRating = 'strict' AllowStickersAndMemes = $True AllowCustomMemes = $True AllowGuestCreateUpdateChannels = $true AllowGuestDeleteChannels = $true - Ensure = "Present" - Credential = $Credscredential + Ensure = 'Present' + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint } } } diff --git a/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 index ca1d20dd85..f181ac8ce2 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCPermissions.psm1 @@ -1279,7 +1279,7 @@ Update-M365DSCAzureAdApplication -ApplicationName 'Microsoft365DSC' -Permissions Update-M365DSCAzureAdApplication -ApplicationName 'Microsoft365DSC' -Permissions @(@{Api='SharePoint';PermissionName='Sites.FullControl.All'},@{Api='Graph';PermissionName='Group.ReadWrite.All'},@{Api='Exchange';PermissionName='Exchange.ManageAsApp'}) -AdminConsent -Credential $creds -Type Certificate -CertificatePath c:\Temp\M365DSC.cer .EXAMPLE -Update-M365DSCAzureAdApplication -ApplicationName $Microsoft365DSC -Permissions $(Get-M365DSCCompiledPermissionList -ResourceNameList Get-M365DSCAllResources -PermissionType Application -AccessType Read) -Type Certificate -CreateSelfSignedCertificate -AdminConsent -MonthsValid 12 -Credential $creds -CertificatePath c:\Temp\M365DSC.cer +Update-M365DSCAzureAdApplication -ApplicationName $Microsoft365DSC -Permissions $(Get-M365DSCCompiledPermissionList -ResourceNameList (Get-M365DSCAllResources) -PermissionType Application -AccessType Read) -Type Certificate -CreateSelfSignedCertificate -AdminConsent -MonthsValid 12 -Credential $creds -CertificatePath c:\Temp\M365DSC.cer .Functionality diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTeamsProtectionPolicy.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTeamsProtectionPolicy.Tests.ps1 new file mode 100644 index 0000000000..0df417aa3c --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.EXOTeamsProtectionPolicy.Tests.ps1 @@ -0,0 +1,184 @@ +[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 'EXOTeamsProtectionPolicy' -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + + BeforeAll { + $secpasswd = ConvertTo-SecureString ((New-Guid).ToString()) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + $Global:PartialExportFileName = 'c:\TestPath' + + + Mock -CommandName Save-M365DSCPartialExport -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return 'Credentials' + } + + Mock -CommandName Set-TeamsProtectionPolicy -MockWith { + } + + Mock -CommandName New-TeamsProtectionPolicy -MockWith { + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + + # Test contexts + Context -Name "When the policy doesn't already exist" -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = "Yes" + AdminDisplayName = "Contoso Administrator" + HighConfidencePhishQuarantineTag = "DefaultFullAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $true + Credential = $Credential + } + + Mock -CommandName Get-TeamsProtectionPolicy -MockWith { + return $null + } + } + + It 'Should return absent from the Get method' { + $result = (Get-TargetResource @testParams) + $result.AdminDisplayName | Should -BeNullOrEmpty + $result.HighConfidencePhishQuarantineTag | Should -BeNullOrEmpty + $result.MalwareQuarantineTag | Should -BeNullOrEmpty + $result.ZapEnabled | Should -BeNullOrEmpty + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create the policy from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName 'New-TeamsProtectionPolicy' -Exactly 1 + Should -Invoke -CommandName 'Set-TeamsProtectionPolicy' -Exactly 1 + } + } + + Context -Name 'When the policy already exists and IS in the Desired State' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = "Yes" + AdminDisplayName = "Contoso Administrator" + HighConfidencePhishQuarantineTag = "DefaultFullAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $true + Credential = $Credential + } + + Mock -CommandName Get-TeamsProtectionPolicy -MockWith { + return @{ + AdminDisplayName = "Contoso Administrator" + HighConfidencePhishQuarantineTag = "DefaultFullAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $true + } + } + } + + It 'Should return absent from the Get method' { + $result = (Get-TargetResource @testParams) + $result.AdminDisplayName | Should -Be $testParams.AdminDisplayName + $result.HighConfidencePhishQuarantineTag | Should -Be $testParams.HighConfidencePhishQuarantineTag + $result.MalwareQuarantineTag | Should -Be $testParams.MalwareQuarantineTag + $result.ZapEnabled | Should -Be $testParams.ZapEnabled + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name 'When the policy already exists and is NOT in the Desired State' -Fixture { + BeforeAll { + $testParams = @{ + IsSingleInstance = "Yes" + AdminDisplayName = "Contoso Administrator" + HighConfidencePhishQuarantineTag = "DefaultFullAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $true + Credential = $Credential + } + + Mock -CommandName Get-TeamsProtectionPolicy -MockWith { + return @{ + AdminDisplayName = "" + HighConfidencePhishQuarantineTag = "AdminOnlyAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $false + } + } + } + + It 'Should return absent from the Get method' { + $result = (Get-TargetResource @testParams) + $result.AdminDisplayName | Should -BeNullOrEmpty + $result.HighConfidencePhishQuarantineTag | Should -Be "AdminOnlyAccessPolicy" + $result.MalwareQuarantineTag | Should -Be "AdminOnlyAccessPolicy" + $result.ZapEnabled | Should -Be $false + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should create the policy from the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName 'Set-TeamsProtectionPolicy' -Exactly 1 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $testParams = @{ + Credential = $Credential + } + + Mock -CommandName Get-TeamsProtectionPolicy -MockWith { + return @{ + AdminDisplayName = "Contoso Administrator" + HighConfidencePhishQuarantineTag = "AdminOnlyAccessPolicy" + MalwareQuarantineTag = "AdminOnlyAccessPolicy" + ZapEnabled = $true + } + } + } + + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope diff --git a/Tests/Unit/Stubs/Microsoft365.psm1 b/Tests/Unit/Stubs/Microsoft365.psm1 index e3024b7ad6..7ae62a90b4 100644 --- a/Tests/Unit/Stubs/Microsoft365.psm1 +++ b/Tests/Unit/Stubs/Microsoft365.psm1 @@ -104707,6 +104707,156 @@ function Get-MgBetaRoleManagementDirectoryRoleAssignmentScheduleRequest ) } #endregion + +#region TeamsProtectionPolicy +function Get-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.Object] + $Identity + ) +} + +function New-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object] + $Organization, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Set-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $AdminDisplayName, + + [Parameter()] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} +#endregion + +#region TeamsProtectionPolicy +function Get-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.Object] + $Identity + ) +} + +function New-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.String] + $Name, + + [Parameter()] + [System.Object] + $Organization, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} + +function Set-TeamsProtectionPolicy +{ + [CmdletBinding()] + param + ( + [Parameter()] + [System.String] + $AdminDisplayName, + + [Parameter()] + [System.String] + $HighConfidencePhishQuarantineTag, + + [Parameter()] + [System.Object] + $Identity, + + [Parameter()] + [System.String] + $MalwareQuarantineTag, + + [Parameter()] + [System.Boolean] + $ZapEnabled, + + [Parameter()] + [System.Management.Automation.SwitchParameter] + $Confirm + ) +} +#endregion #region MgBetaDeviceManagementRoleScopeTagAssignment function Get-MgBetaDeviceManagementRoleScopeTagAssignment {