Skip to content

Commit

Permalink
Merge pull request #3754 from swisscom/fix/TeamsComplianceRecordingPo…
Browse files Browse the repository at this point in the history
…licy

Fix/teams compliance recording policy
  • Loading branch information
NikCharlebois authored Oct 2, 2024
2 parents ec6970f + 71034c6 commit 3f4e1e2
Show file tree
Hide file tree
Showing 5 changed files with 293 additions and 49 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,8 @@
* Added EnableAIPIntegration.
* TeamsChannelTab
* Fixed schema file
* TeamsComplianceRecordingPolicy
* FIXES [[#3712](https://github.com/microsoft/Microsoft365DSC/issues/3712)]
* TeamsGroupPolicyAssignment
* Skip assignments that have orphaned/deleted groups or without display name
instead of throwing an error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ function Get-TargetResource
$Identity,

[Parameter()]
[System.String[]]
[Microsoft.Management.Infrastructure.CimInstance[]]
$ComplianceRecordingApplications,

[Parameter()]
Expand Down Expand Up @@ -82,20 +82,40 @@ function Get-TargetResource
{
return $nullResult
}
$recordingApplications = [Array](Get-CsTeamsComplianceRecordingApplication -Filter "$($instance.Identity)/*")
if ($null -eq $recordingApplications)

if ($instance.ComplianceRecordingApplications.Count -gt 0)
{
$recordingApplications = @()
}
$recordApplicationIds = @()
foreach ($app in $recordingApplications) {
$recordApplicationIds += $app.Id
$ComplexComplianceRecordingApplications = @()
foreach ($CurrentComplianceRecordingApplications in $instance.ComplianceRecordingApplications)
{
$MyComplianceRecordingApplications = @{}
$ComplianceRecordingPairedApplications = @()
if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0)
{
foreach ($CurrentComplianceRecordingPairedApplications in $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications)
{
$ComplianceRecordingPairedApplications += $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Id
}
}
$MyComplianceRecordingApplications.Add('ComplianceRecordingPairedApplications', $ComplianceRecordingPairedApplications)
$MyComplianceRecordingApplications.Add('Id', $CurrentComplianceRecordingApplications.Id)
$MyComplianceRecordingApplications.Add('RequiredBeforeMeetingJoin', $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin)
$MyComplianceRecordingApplications.Add('RequiredBeforeCallEstablishment', $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment)
$MyComplianceRecordingApplications.Add('RequiredDuringMeeting', $CurrentComplianceRecordingApplications.RequiredDuringMeeting)
$MyComplianceRecordingApplications.Add('RequiredDuringCall', $CurrentComplianceRecordingApplications.RequiredDuringCall)
$MyComplianceRecordingApplications.Add('ConcurrentInvitationCount', $CurrentComplianceRecordingApplications.ConcurrentInvitationCount)

if ($MyComplianceRecordingApplications.values.Where({ $null -ne $_ }).count -gt 0)
{
$ComplexComplianceRecordingApplications += $MyComplianceRecordingApplications
}
}
}

Write-Verbose -Message "Found an instance with Identity {$Identity}"
$results = @{
Identity = $instance.Identity
ComplianceRecordingApplications = $recordApplicationIds
ComplianceRecordingApplications = $ComplexComplianceRecordingApplications
Description = $instance.Description
DisableComplianceRecordingAudioNotificationForCalls = $instance.DisableComplianceRecordingAudioNotificationForCalls
Enabled = $instance.Enabled
Expand Down Expand Up @@ -132,7 +152,7 @@ function Set-TargetResource
$Identity,

[Parameter()]
[System.String[]]
[Microsoft.Management.Infrastructure.CimInstance[]]
$ComplianceRecordingApplications,

[Parameter()]
Expand Down Expand Up @@ -218,13 +238,60 @@ function Set-TargetResource
{
if ($null -ne $CreateParameters.$key -and $CreateParameters.$key.GetType().Name -like '*cimInstance*')
{
$keyName = $key.substring(0, 1).ToLower() + $key.substring(1, $key.length - 1)
$keyValue = Convert-M365DSCDRGComplexTypeToHashtable -ComplexObject $CreateParameters.$key
$CreateParameters.Remove($key) | Out-Null
$CreateParameters.Add($keyName, $keyValue)
}
}
Write-Verbose -Message "Creating {$Identity} with Parameters:`r`n$(Convert-M365DscHashtableToString -Hashtable $CreateParameters)"
New-CsTeamsComplianceRecordingPolicy @CreateParameters | Out-Null

if ($ComplianceRecordingApplications.Count -gt 0)
{
foreach ($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications)
{
$Instance = $CurrentComplianceRecordingApplications.Id
$RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin
$RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment
$RequiredDuringMeeting = $CurrentComplianceRecordingApplications.RequiredDuringMeeting
$RequiredDuringCall = $CurrentComplianceRecordingApplications.RequiredDuringCall
$ConcurrentInvitationCount = $CurrentComplianceRecordingApplications.ConcurrentInvitationCount

$CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue
if ($null -eq $CsTeamsComplianceRecordingApplication)
{
New-CsTeamsComplianceRecordingApplication `
-RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin `
-RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment `
-RequiredDuringMeeting $RequiredDuringMeeting `
-RequiredDuringCall $RequiredDuringCall `
-ConcurrentInvitationCount $ConcurrentInvitationCount `
-Parent $Identity -Id $Instance
}
else
{
Set-CsTeamsComplianceRecordingApplication `
-Identity $CsTeamsComplianceRecordingApplicationIdentity `
-RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin `
-RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment `
-RequiredDuringMeeting $RequiredDuringMeeting `
-RequiredDuringCall $RequiredDuringCall `
-ConcurrentInvitationCount $ConcurrentInvitationCount
}

if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0)
{
Set-CsTeamsComplianceRecordingApplication `
-Identity "$Identity + '/' + $Instance" `
-ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication `
-Id $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications)
}
}
$NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object { $_.Identity -match $Identity }
Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication
}

}
elseif ($Ensure -eq 'Present' -and $currentInstance.Ensure -eq 'Present')
{
Expand All @@ -245,6 +312,51 @@ function Set-TargetResource
}

Set-CsTeamsComplianceRecordingPolicy @UpdateParameters | Out-Null
if ($ComplianceRecordingApplications.Count -gt 0)
{
foreach ($CurrentComplianceRecordingApplications in $ComplianceRecordingApplications)
{
$Instance = $CurrentComplianceRecordingApplications.Id
$RequiredBeforeMeetingJoin = $CurrentComplianceRecordingApplications.RequiredBeforeMeetingJoin
$RequiredBeforeCallEstablishment = $CurrentComplianceRecordingApplications.RequiredBeforeCallEstablishment
$RequiredDuringMeeting = $CurrentComplianceRecordingApplications.RequiredDuringMeeting
$RequiredDuringCall = $CurrentComplianceRecordingApplications.RequiredDuringCall
$ConcurrentInvitationCount = $CurrentComplianceRecordingApplications.ConcurrentInvitationCount

$CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance

$CsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ErrorAction SilentlyContinue
if ($null -eq $CsTeamsComplianceRecordingApplication)
{
New-CsTeamsComplianceRecordingApplication `
-RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin `
-RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment `
-RequiredDuringMeeting $RequiredDuringMeeting `
-RequiredDuringCall $RequiredDuringCall `
-ConcurrentInvitationCount $ConcurrentInvitationCount `
-Parent $Identity -Id $Instance
}
else
{
Set-CsTeamsComplianceRecordingApplication `
-Identity $CsTeamsComplianceRecordingApplicationIdentity `
-RequiredBeforeMeetingJoin $RequiredBeforeMeetingJoin `
-RequiredBeforeCallEstablishment $RequiredBeforeCallEstablishment `
-RequiredDuringMeeting $RequiredDuringMeeting `
-RequiredDuringCall $RequiredDuringCall `
-ConcurrentInvitationCount $ConcurrentInvitationCount
}

if ($CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications.Count -gt 0)
{
[string]$CsTeamsComplianceRecordingApplicationIdentity = $Identity + '/' + $Instance
[string]$ComplianceRecordingPairedApplications = $CurrentComplianceRecordingApplications.ComplianceRecordingPairedApplications
Set-CsTeamsComplianceRecordingApplication -Identity $CsTeamsComplianceRecordingApplicationIdentity -ComplianceRecordingPairedApplications @(New-CsTeamsComplianceRecordingPairedApplication -Id $ComplianceRecordingPairedApplications)
}
}
$NewCsTeamsComplianceRecordingApplication = Get-CsTeamsComplianceRecordingApplication | Where-Object { $_.Identity -match $Identity }
Set-CsTeamsComplianceRecordingPolicy -Identity $Identity -ComplianceRecordingApplications $NewCsTeamsComplianceRecordingApplication
}
}
elseif ($Ensure -eq 'Absent' -and $currentInstance.Ensure -eq 'Present')
{
Expand All @@ -264,7 +376,7 @@ function Test-TargetResource
$Identity,

[Parameter()]
[System.String[]]
[Microsoft.Management.Infrastructure.CimInstance[]]
$ComplianceRecordingApplications,

[Parameter()]
Expand Down Expand Up @@ -336,6 +448,30 @@ function Test-TargetResource
Write-Verbose -Message "Test-TargetResource returned $false"
return $false
}
$testResult = $true

#Compare Cim instances
foreach ($key in $PSBoundParameters.Keys)
{
$source = $PSBoundParameters.$key
$target = $CurrentValues.$key
if ($source.getType().Name -like '*CimInstance*')
{
$source = Get-M365DSCDRGComplexTypeToHashtable -ComplexObject $source

$testResult = Compare-M365DSCComplexObject `
-Source ($source) `
-Target ($target)

if (-Not $testResult)
{
$testResult = $false
break
}

$ValuesToCheck.Remove($key) | Out-Null
}
}

Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)"
Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)"
Expand All @@ -350,10 +486,13 @@ function Test-TargetResource
}
}

$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"

Expand Down Expand Up @@ -452,11 +591,42 @@ function Export-TargetResource
$Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode `
-Results $Results

if ($null -ne $Results.ComplianceRecordingApplications)
{
$complexMapping = @(
@{
Name = 'ComplianceRecordingApplications'
CimInstanceName = 'TeamsComplianceRecordingApplication'
IsRequired = $False
}
)
$complexTypeStringResult = Get-M365DSCDRGComplexTypeToString `
-ComplexObject $Results.ComplianceRecordingApplications `
-CIMInstanceName 'TeamsComplianceRecordingApplication' `
-ComplexTypeMapping $complexMapping

if (-Not [String]::IsNullOrWhiteSpace($complexTypeStringResult))
{
$Results.ComplianceRecordingApplications = $complexTypeStringResult
}
else
{
$Results.Remove('ComplianceRecordingApplications') | Out-Null
}
}

$currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName `
-ConnectionMode $ConnectionMode `
-ModulePath $PSScriptRoot `
-Results $Results `
-Credential $Credential
if ($Results.ComplianceRecordingApplications)
{
$currentDSCBlock = Convert-DSCStringParamToVariable -DSCBlock $currentDSCBlock -ParameterName 'ComplianceRecordingApplications' -IsCIMArray:$True
$currentDSCBlock = $currentDSCBlock.Replace('ComplianceRecordingApplications = @("', 'ComplianceRecordingApplications = @(')
$currentDSCBlock = $currentDSCBlock.Replace(" `",`"`r`n", '')

}
$dscContent += $currentDSCBlock
Save-M365DSCPartialExport -Content $currentDSCBlock `
-FileName $Global:PartialExportFileName
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
[ClassVersion("1.0.0")]
class MSFT_TeamsComplianceRecordingApplication
{
[Write, Description("A name that uniquely identifies the application instance of the policy-based recording application.")] String Id;
[Write, Description("Determines the other policy-based recording applications to pair with this application to achieve application resiliency. Can only have one paired application.")] String ComplianceRecordingPairedApplications[];
[Write, Description("Indicates whether the policy-based recording application must be in the meeting before the user is allowed to join the meeting.")] Boolean RequiredBeforeMeetingJoin;
[Write, Description("Indicates whether the policy-based recording application must be in the call before the call is allowed to establish.")] Boolean RequiredBeforeCallEstablishment;
[Write, Description("Indicates whether the policy-based recording application must be in the meeting while the user is in the meeting.")] Boolean RequiredDuringMeeting;
[Write, Description("Indicates whether the policy-based recording application must be in the call while the call is active.")] Boolean RequiredDuringCall;
[Write, Description("Determines the number of invites to send out to the application instance of the policy-based recording application. Can be set to 1 or 2 only.")] String ConcurrentInvitationCount;
};

[ClassVersion("1.0.0.0"), FriendlyName("TeamsComplianceRecordingPolicy")]
class MSFT_TeamsComplianceRecordingPolicy : OMI_BaseResource
{
[Key, Description("Unique identifier of the application instance of a policy-based recording application to be retrieved.")] String Identity;
[Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet.")] String ComplianceRecordingApplications[];
[Write, Description("A list of application instances of policy-based recording applications to assign to this policy. The Id of each of these application instances must be the ObjectId of the application instance as obtained by the Get-CsOnlineApplicationInstance cmdlet."), EmbeddedInstance("MSFT_TeamsComplianceRecordingApplication")] String ComplianceRecordingApplications[];
[Write, Description("Enables administrators to provide explanatory text to accompany a Teams recording policy. For example, the Description might include information about the users the policy should be assigned to.")] String Description;
[Write, Description("Setting this attribute to true disables recording audio notifications for 1:1 calls that are under compliance recording.")] Boolean DisableComplianceRecordingAudioNotificationForCalls;
[Write, Description("Controls whether this Teams recording policy is active or not.")] Boolean Enabled;
Expand Down
Loading

0 comments on commit 3f4e1e2

Please sign in to comment.