Cayosoft.Graph.psm1
<#
.SYNOPSIS Export Dynamic Group rule configuration from Cayosoft Administrator to a CSV file. .DESCRIPTION Export Dynamic Group rule configuration from Cayosoft Administrator to a CSV file. .PARAMETER FileName Specifies the output CSV file name. .PARAMETER IncludeSchedule Specifies if to include rule schedule to the export file. .PARAMETER ManagedSystem Specifies Cayosoft Administrator Dynamic Group rule type to process. .PARAMETER IncludeRuleOutput Specifies if to include Dynamic Group rule output settings. .PARAMETER CsvSeparator Specifies separator symbol for the output CSV file. .PARAMETER Name Specifies one or more Dynamic Group rule names to export. If not set all Dynamic Group rules are exported. .PARAMETER Container Specifies one or more containers with Dynamic Group rules. When not set, all Dynamic Group rules for the specified managed system are exported. .PARAMETER ShowBanner If set cmdlet prints version information. .EXAMPLE C:\PS> Export-CGDynamicGroup -FileName C:\Temp\output.csv -Name "GroupName" -IncludeSchedule Description ----------- This example exports Active Directory Dynamic Group settings with its schedule to the CSV file. .NOTES . #> function Export-CGDynamicGroup { [CmdletBinding()] param( [Parameter(Mandatory=$True)] [string]$FileName, [Parameter(Mandatory=$False)] [Switch]$IncludeSchedule, [Parameter(Mandatory=$False)] [ValidateSet("AD", "Microsoft365")] [string]$ManagedSystem="AD", [Parameter(Mandatory=$False)] [Switch]$IncludeRuleOutput, [Parameter(Mandatory=$False)] [char]$CsvSeparator=',', [Parameter(Mandatory=$False)] [string[]]$Name, [Parameter(Mandatory=$False)] [string[]]$Container, [Parameter(Mandatory=$False)] [switch]$ShowBanner = $False ) begin { $CGraphModule = "Cayo.Graph.PowerShell.dll" $CGraphModulePath = [System.IO.Path]::Combine($PSScriptRoot, $CGraphModule) if ([System.IO.File]::Exists($CGraphModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Graph PowerShell Module to be installed on this machine." } Import-Module $CGraphModulePath | Out-Null [Cayo.Graph.PowerShell.DynamicGroups.ModuleIntializer]::Initialize() $CAModule = "Cayo.PolicyManager.Common.dll" $CAModulePath = [System.IO.Path]::Combine("C:\Program Files\Cayo Software\AdminAssistant", $CAModule) if ([System.IO.File]::Exists($CAModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Administrator to be installed on this machine." } [Reflection.Assembly]::LoadFrom($CAModulePath) | Out-Null } process { if ($ShowBanner -eq $true) { Write-Host -ForegroundColor Yellow "" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "Version: $($MyInvocation.MyCommand.Module.Version)" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "" } $context = @{ "IncludeSchedule"=$IncludeSchedule; "IncludeRuleOutput"=$IncludeRuleOutput; "ManagedSystem"=$ManagedSystem; "GroupName"=$Name; "GroupContainers"=$Container } $rows = @() try { $tgtGroups = LoadDGsAsList $tgtGroups | ?{ ((($context.ManagedSystem -eq "AD" -and $_.TargetExtension -eq "PM.Ext.AD") -or ($context.ManagedSystem -eq "Microsoft365" -and $_.TargetExtension -eq "Office365Ext")) -and ($context.GroupName -eq $null -or ($_.Name -eq ($context.GroupName -eq $_.Name))) -and ($context.GroupContainers -eq $null -or ($null -ne ($_.Labels | ?{ $_ -eq ($context.GroupContainers -eq $_)}))))} | %{ (GetDGRows $_ $context) | %{$rows+=$_} } $rows | Export-Csv -Path $FileName -NoTypeInformation -Encoding UTF8 -Delimiter $CsvSeparator } catch { $err = $_ } if ($null -eq $err) { Log "Export completed successfully. Total exported rules: $($rows.Count)" } else { LogError "Export completed with error: $($err)" } } } <# .SYNOPSIS Imports Dynamic Group rule configuration from a CSV file to the Cayosoft Administrator. .DESCRIPTION Imports Dynamic Group rule configuration from a CSV file to the Cayosoft Administrator. .PARAMETER FileName Specifies the input CSV file name. .PARAMETER IncludeSchedule Specifies if to include rule schedule from the import file. .PARAMETER ManagedSystem Specifies Cayosoft Administrator Dynamic Group rule type to process. .PARAMETER IncludeRuleOutput Specifies if to include Dynamic Group rule output settings. .PARAMETER DefaultParameters Specifies membership command parameters that will be overwritten on import. .PARAMETER CsvSeparator Specifies separator symbol for the output CSV file. .PARAMETER CompareMembers If set, future membership calculated by the imported Dynamic Group rule will be compared to the current group membership, and the difference would be reported to the command output. .PARAMETER ImportMode Specifies how to merge Dynamic Group membership commands. For Append mode imported membership commands will be added to the current list of membership commands. For Replace mode imported membership commands will overwrite the existing membership commands. .PARAMETER Credential Specifies connection credentials. Active Directory or Microsoft 365 credentials can be supplied, depending on the ManagedSystem parameter value. .PARAMETER DC Specifies Domain Controller DNS name or Microsoft 365 tenant name. .PARAMETER MoveToContainer Specifies container to move all imported Dynamic Groups. .PARAMETER ReportFileName Specifies file name to store report with the results of the import. .PARAMETER StopOnScopeResolutionError Stop processing the import file if Include or Exclude Explicitly rule scope object could not be resolved. .PARAMETER ShowBanner If set cmdlet prints version information. .EXAMPLE C:\PS> Import-CGDynamicGroup -ImportMode Append -FileName C:\Temp\output.csv -DC "DCName" -Credential $credential Description ----------- This example adds new membership rules from the CSV file to the existing Active Directory Dynamic Group. .NOTES . #> function Import-CGDynamicGroup { [CmdletBinding()] param( [Parameter(Mandatory=$True)] [string]$FileName, [Parameter(Mandatory=$False)] [Switch]$IncludeSchedule, [Parameter(Mandatory=$False)] [ValidateSet("AD", "Microsoft365")] [string]$ManagedSystem="AD", [Parameter(Mandatory=$False)] [Switch]$IncludeRuleOutput, [Parameter(Mandatory=$False)] [Hashtable]$DefaultParameters, [Parameter(Mandatory=$False)] [char]$CsvSeparator=',', [Parameter(Mandatory=$False)] [Switch]$CompareMembers, [Parameter(Mandatory=$False)] [ValidateSet("Append", "Replace")] [string]$ImportMode="Append", [Parameter(Mandatory=$False)] [System.Management.Automation.PSCredential]$Credential, [Parameter(Mandatory=$False)] [Alias("Tenant")] [string]$DC, [Parameter(Mandatory=$False)] [string]$MoveToContainer, [Parameter(Mandatory=$False)] [string]$ReportFileName, [Parameter(Mandatory=$False)] [switch]$StopOnScopeResolutionError, [Parameter(Mandatory=$False)] [switch]$ShowBanner = $False ) begin { $CGraphModule = "Cayo.Graph.PowerShell.dll" $CGraphModulePath = [System.IO.Path]::Combine($PSScriptRoot, $CGraphModule) if ([System.IO.File]::Exists($CGraphModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Graph PowerShell Module to be installed on this machine." } Import-Module $CGraphModulePath | Out-Null [Cayo.Graph.PowerShell.DynamicGroups.ModuleIntializer]::Initialize() $CAModule = "Cayo.PolicyManager.Common.dll" $CAModulePath = [System.IO.Path]::Combine("C:\Program Files\Cayo Software\AdminAssistant", $CAModule) if ([System.IO.File]::Exists($CAModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Administrator to be installed on this machine." } [Reflection.Assembly]::LoadFrom($CAModulePath) | Out-Null } process { if ($ShowBanner -eq $true) { Write-Host -ForegroundColor Yellow "" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "Version: $($MyInvocation.MyCommand.Module.Version)" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "" } EnsureEncoding $FileName EnsureExtension $ManagedSystem $context = @{ "DnCache"=@{}; "ObjectCache"=@{}; "Credential"=$Credential; "DC"=$DC; "IncludeSchedule"=$IncludeSchedule; "IncludeRuleOutput"=$IncludeRuleOutput; "ImportMode"=$ImportMode; "ManagedSystem"=$ManagedSystem; "DefaultParameters"=$DefaultParameters; "MoveToContainer"=$MoveToContainer; "StopIfIncExpResolveScopeError"=$StopOnScopeResolutionError; "ImportParseReport"=@(); } $isAD = ($context.ManagedSystem -eq "AD") $notUpdated = $null $groupsUpdated = 0 $err = $null try { if ($isAD -eq $False -and $context.Credential -eq $null){throw "Credentials must be specified."} if ($isAD -eq $False -and ([string]::IsNullOrWhiteSpace($context.DC) -eq $True)){throw "Tenant name must be specified."} $tgtGroups = LoadDGs $cayoGroups = (ParseDGRowsFromCsv $FileName $context) if ($null -ne $cayoGroups) { $groupsUpdated = $cayoGroups.Count } $notUpdated = UpdateDGs $cayoGroups $tgtGroups $context if ($null -ne $notUpdated) { $groupsUpdated -= $notUpdated.Count } } catch { $err = $_ } if ([string]::IsNullOrWhiteSpace($ReportFileName) -eq $false) { DumpImportParseReport $context.ImportParseReport $ReportFileName Log "Report location: $($ReportFileName)" } if ($notUpdated -ne $null) { $notUpdated | %{ if($_ -eq $null){return} LogError "Dynamic Group rule was not updated: multiple rules for the same group were found. Group ID: $($_.TargetGroup.Id) Group name: $($_.TargetGroup.DisplayName)" } } if ($null -eq $err) { Log "Import completed successfully. Total rules updated: $($groupsUpdated)" } else { LogError "Import completed with error: $($err)" } if ($null -eq $err -and $CompareMembers -eq $True) { Log "Membership comparison started" if ($isAD -eq $True){CompareAdMembership $cayoGroups $context} else{CompareO365Membership $cayoGroups $context} Log "Membership comparison completed" } } } <# .SYNOPSIS Deletes Dynamic Group rule configuration from the Cayosoft Administrator based on input CSV file. .DESCRIPTION Deletes Dynamic Group rule configuration from the Cayosoft Administrator based on input CSV file. .PARAMETER FileName Specifies input CSV file name contains Dynamic Group rules to delete. Supports Cayosoft Dynamic Group CSV format only. .PARAMETER CsvSeparator Specifies separator symbol for the output CSV file. .PARAMETER ShowBanner If set cmdlet prints version information. .EXAMPLE C:\PS> Remove-CGDynamicGroup -FileName C:\Temp\output.csv Description ----------- This example deletes Dynamic Group rules specified in the CSV file. .NOTES . #> function Remove-CGDynamicGroup { [CmdletBinding()] param( [Parameter(Mandatory=$True)] [string]$FileName, [Parameter(Mandatory=$False)] [char]$CsvSeparator=',', [Parameter(Mandatory=$False)] [switch]$ShowBanner = $False ) begin { $CGraphModule = "Cayo.Graph.PowerShell.dll" $CGraphModulePath = [System.IO.Path]::Combine($PSScriptRoot, $CGraphModule) if ([System.IO.File]::Exists($CGraphModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Graph PowerShell Module to be installed on this machine." } Import-Module $CGraphModulePath | Out-Null [Cayo.Graph.PowerShell.DynamicGroups.ModuleIntializer]::Initialize() $CAModule = "Cayo.PolicyManager.Common.dll" $CAModulePath = [System.IO.Path]::Combine("C:\Program Files\Cayo Software\AdminAssistant", $CAModule) if ([System.IO.File]::Exists($CAModulePath) -eq $False) { throw "This cmdlet requires Cayosoft Administrator to be installed on this machine." } [Reflection.Assembly]::LoadFrom($CAModulePath) | Out-Null } process { if ($ShowBanner -eq $true) { Write-Host -ForegroundColor Yellow "" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "Version: $($MyInvocation.MyCommand.Module.Version)" Write-Host -ForegroundColor Yellow "----------------------------------------------------------------------------" Write-Host -ForegroundColor Yellow "" } $context = @{ } $notUpdated = $null $groupsUpdated = 0 EnsureEncoding $FileName try { $cayoGroups = LoadDGsAsList $csvGroups = (ParseDGRowsToDeleteFromCsv $FileName $context) $toDelete = @{} if ($null -ne $csvGroups) { $csvGroups.GetEnumerator() | %{ if ($null -eq $_) { return } $csvGroup = $_ $cayoGroup = $cayoGroups | ?{ $null -ne $_.TargetGroup -and $_.TargetGroup.Id -eq $csvGroup.Key } if ($null -ne $cayoGroup) { $toDelete[$cayoGroup.RuleId] = $null } else { Log "Group not found: $($_.Key)" } } } $groupsUpdated = $toDelete.Count $notUpdated = DeleteDGs ($toDelete.GetEnumerator() | %{ $_.Key }) $context if ($null -ne $notUpdated) { $groupsUpdated -= $notUpdated.Count } } catch { $err = $_ } if ($null -eq $err) { Log "Delete completed successfully. Total rules deleted: $($groupsUpdated)" } else { LogError "Deletion completed with error: $($err)" } } } # SIG # Begin signature block # MIIgKQYJKoZIhvcNAQcCoIIgGjCCIBYCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBVmRkHCVP0Ge1G # lGV+G0mO9MK+5LRo5M6RJnp8cQRQDqCCGxEwggT+MIID5qADAgECAhANQkrgvjqI # /2BAIc4UAPDdMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNV # BAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwHhcN # MjEwMTAxMDAwMDAwWhcNMzEwMTA2MDAwMDAwWjBIMQswCQYDVQQGEwJVUzEXMBUG # A1UEChMORGlnaUNlcnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFt # cCAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwuZhhGfFivUN # CKRFymNrUdc6EUK9CnV1TZS0DFC1JhD+HchvkWsMlucaXEjvROW/m2HNFZFiWrj/ # ZwucY/02aoH6KfjdK3CF3gIY83htvH35x20JPb5qdofpir34hF0edsnkxnZ2OlPR # 0dNaNo/Go+EvGzq3YdZz7E5tM4p8XUUtS7FQ5kE6N1aG3JMjjfdQJehk5t3Tjy9X # tYcg6w6OLNUj2vRNeEbjA4MxKUpcDDGKSoyIxfcwWvkUrxVfbENJCf0mI1P2jWPo # GqtbsR0wwptpgrTb/FZUvB+hh6u+elsKIC9LCcmVp42y+tZji06lchzun3oBc/gZ # 1v4NSYS9AQIDAQABo4IBuDCCAbQwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQC # MAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwQQYDVR0gBDowODA2BglghkgBhv1s # BwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMB8G # A1UdIwQYMBaAFPS24SAd/imu0uRhpbKiJbLIFzVuMB0GA1UdDgQWBBQ2RIaOpLqw # Zr68KC0dRDbd42p6vDBxBgNVHR8EajBoMDKgMKAuhixodHRwOi8vY3JsMy5kaWdp # Y2VydC5jb20vc2hhMi1hc3N1cmVkLXRzLmNybDAyoDCgLoYsaHR0cDovL2NybDQu # ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwgYUGCCsGAQUFBwEBBHkw # dzAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME8GCCsGAQUF # BzAChkNodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNz # dXJlZElEVGltZXN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4IBAQBIHNy1 # 6ZojvOca5yAOjmdG/UJyUXQKI0ejq5LSJcRwWb4UoOUngaVNFBUZB3nw0QTDhtk7 # vf5EAmZN7WmkD/a4cM9i6PVRSnh5Nnont/PnUp+Tp+1DnnvntN1BIon7h6JGA078 # 9P63ZHdjXyNSaYOC+hpT7ZDMjaEXcw3082U5cEvznNZ6e9oMvD0y0BvL9WH8dQgA # dryBDvjA4VzPxBFy5xtkSdgimnUVQvUtMjiB2vRgorq0Uvtc4GEkJU+y38kpqHND # Udq9Y9YfW5v3LhtPEx33Sg1xfpe39D+E68Hjo0mh+s6nv1bPull2YYlffqe0jmd4 # +TaY4cso2luHpoovMIIFMTCCBBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkq # hkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB # c3N1cmVkIElEIFJvb3QgQ0EwHhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAw # WjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL # ExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3Vy # ZWQgSUQgVGltZXN0YW1waW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB # CgKCAQEAvdAy7kvNj3/dqbqCmcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI # 5Je/YyGQmL8TvFfTw+F+CNZqFAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+ # wKL1oODeIj8O/36V+/OjuiI+GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91 # z3FyTgqt30A6XLdR4aF5FMZNJCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmE # UeaC50ZQ/ZQqLKfkdT66mA+Ef58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9 # olMqT4UdxB08r8/arBD13ays6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS2 # 4SAd/imu0uRhpbKiJbLIFzVuMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3z # bcgPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQM # MAoGCCsGAQUFBwMIMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDov # L29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5k # aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8E # ejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1 # cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v # RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9 # bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT # MAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpj # erN4zwY3QITvS4S/ys8DAv3Fp8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg # 33akOpMP+LLR2HwZYuhegiUexLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQ # GF+JOGFNYkYkh2OMkVIsrymJ5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuW # wPRYaQ18yAGxuSh1t5ljhSKMYcp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLStt # osR+u8QlK0cCCHxJrhO24XxCQijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaO # UjCCBVgwggRAoAMCAQICEDmbQN4+QWKelMjw2vBuowIwDQYJKoZIhvcNAQELBQAw # fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G # A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD # ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMjAwNzI4MDAwMDAwWhcN # MjMwNzI4MjM1OTU5WjCBoTELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTQzMDgyMQ0w # CwYDVQQIDARPaGlvMRQwEgYDVQQHDAtXZXN0ZXJ2aWxsZTEtMCsGA1UECQwkNDcw # IE9sZGUgV29ydGhpbmd0b24gUm9hZCwgU3VpdGUgMjAwMRYwFAYDVQQKDA1DYXlv # c29mdCBJbmMuMRYwFAYDVQQDDA1DYXlvc29mdCBJbmMuMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEAxuvkAYYnxOw86PW0+BUdChz31k1g4KGjE99h2UqV # ayTI0d/3M5fWUhLGoxDddtVrY0npbSawavn4obqSmML2ZLspPhX10IJ/h7er7mx/ # u2q86A1YXSqLMrXRbioPldbdnTplbVkULvR2QjUXC9wIyC00j7hGhj+RI5frtJXw # eQXtUGacdfaKoshT5cg8yaat46/l6Vi91Dro2NhWRcK/081iQyJ+lLdqoTsmfiwT # mrmUEedcyldneA3PthTa9NrfwioGDx3jW5AEvFcsknMByY4NSjJ2I5oZt+80e/tQ # YaNrMVLDHSVmPYfADGHJlpcKB2zKsFFbzJLx1bH89j+DBQIDAQABo4IBrjCCAaow # HwYDVR0jBBgwFoAUDuE6qFM6MdWKvsG7rWcaA4WtNA4wHQYDVR0OBBYEFPJ63HfM # WRV8zYLoKRGjbTW9ozu/MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMG # A1UdJQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBKBgNVHSAEQzBB # MDUGDCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3RpZ28u # Y29tL0NQUzAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5z # ZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdDQS5jcmwwcwYIKwYBBQUH # AQEEZzBlMD4GCCsGAQUFBzAChjJodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3Rp # Z29SU0FDb2RlU2lnbmluZ0NBLmNydDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Au # c2VjdGlnby5jb20wHAYDVR0RBBUwE4ERaW5mb0BjYXlvc29mdC5jb20wDQYJKoZI # hvcNAQELBQADggEBACDAJy/sZI8y6BqvC9vixj2U3mySLcutLD0KxG3x71z4LJs8 # bMU8qTVo76fYIL8ZbfgpNvRa9Ba8HvfdyPP/Ih5aG1DwC/jbtPW6q813q9oh3TrS # lY1AkGnSVeK5Md3dB3B+5md7A4CX/cB9l8P98kjn4o2Ydoo63QVDTqwUvy7skXx8 # 9nrPiRsYgDIwFknSrJfd3s6Tr5KPfttXltwt49iPpEyMQKtHpg053sONbr1eMew3 # TfGbaE+qQw1wSRf04YSBcOrA7S2s0yDuGKQWg0o7TYyup6uXEM+WHYWkOJMquJYj # yF4wz71q3dEt7vh7QzgYVDCyVMN7f8XSfRwGQz4wggWBMIIEaaADAgECAhA5ckQ6 # +SK3UdfTbBDdMTWVMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYD # VQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNV # BAoMEUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUg # U2VydmljZXMwHhcNMTkwMzEyMDAwMDAwWhcNMjgxMjMxMjM1OTU5WjCBiDELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBD # aXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVT # RVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3 # DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBN # CS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR # +OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn # RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6v # BZY1H1dat//O+T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZT # mzNg95S+UzeQc0PzMsNT79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M # 0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1 # XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn # 4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexD # JtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZG # SlCBst6+eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt # 7y+CDwIDAQABo4HyMIHvMB8GA1UdIwQYMBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0 # MB0GA1UdDgQWBBRTeb9aqitKz1SA4dibwJ3ysgNmyzAOBgNVHQ8BAf8EBAMCAYYw # DwYDVR0TAQH/BAUwAwEB/zARBgNVHSAECjAIMAYGBFUdIAAwQwYDVR0fBDwwOjA4 # oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2 # aWNlcy5jcmwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz # cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggEBABiHUdx0IT2ciuAntzPQ # Lszs8ObLXhHeIm+bdY6ecv7k1v6qH5yWLe8DSn6u9I1vcjxDO8A/67jfXKqpxq7y # /Njuo3tD9oY2fBTgzfT3P/7euLSK8JGW/v1DZH79zNIBoX19+BkZyUIrE79Yi7qk # omYEdoiRTgyJFM6iTckys7roFBq8cfFb8EELmAAKIgMQ5Qyx+c2SNxntO/HkOrb5 # RRMmda+7qu8/e3c70sQCkT0ZANMXXDnbP3sYDUXNk4WWL13fWRZPP1G91UUYP+1K # jugGYXQjFrUNUHMnREd/EF2JKmuFMRTE6KlqTIC8anjPuH+OdnKZDJ3+15EIFqGj # X5UwggX1MIID3aADAgECAhAdokgwb5smGNCC4JZ9M9NqMA0GCSqGSIb3DQEBDAUA # MIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNleTEUMBIGA1UEBxML # SmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEuMCwG # A1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x # ODExMDIwMDAwMDBaFw0zMDEyMzEyMzU5NTlaMHwxCzAJBgNVBAYTAkdCMRswGQYD # VQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNV # BAoTD1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBT # aWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhiKNMoV6 # GJ9J8JYvYwgeLdx8nxTP4ya2JWYpQIZURnQxYsUQ7bKHJ6aZy5UwwFb1pHXGqQ5Q # YqVRkRBq4Etirv3w+Bisp//uLjMg+gwZiahse60Aw2Gh3GllbR9uJ5bXl1GGpvQn # 5Xxqi5UeW2DVftcWkpwAL2j3l+1qcr44O2Pej79uTEFdEiAIWeg5zY/S1s8GtFcF # tk6hPldrH5i8xGLWGwuNx2YbSp+dgcRyQLXiX+8LRf+jzhemLVWwt7C8VGqdvI1W # U8bwunlQSSz3A7n+L2U18iLqLAevRtn5RhzcjHxxKPP+p8YU3VWRbooRDd8GJJV9 # D6ehfDrahjVh0wIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUU3m/WqorSs9UgOHY # m8Cd8rIDZsswHQYDVR0OBBYEFA7hOqhTOjHVir7Bu61nGgOFrTQOMA4GA1UdDwEB # /wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdJQQWMBQGCCsGAQUFBwMD # BggrBgEFBQcDCDARBgNVHSAECjAIMAYGBFUdIAAwUAYDVR0fBEkwRzBFoEOgQYY/ # aHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUNlcnRpZmljYXRp # b25BdXRob3JpdHkuY3JsMHYGCCsGAQUFBwEBBGowaDA/BggrBgEFBQcwAoYzaHR0 # cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUFkZFRydXN0Q0EuY3J0 # MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3 # DQEBDAUAA4ICAQBNY1DtRzRKYaTb3moqjJvxAAAeHWJ7Otcywvaz4GOz+2EAiJob # bRAHBE++uOqJeCLrD0bs80ZeQEaJEvQLd1qcKkE6/Nb06+f3FZUzw6GDKLfeL+SU # 94Uzgy1KQEi/msJPSrGPJPSzgTfTt2SwpiNqWWhSQl//BOvhdGV5CPWpk95rcUCZ # lrp48bnI4sMIFrGrY1rIFYBtdF5KdX6luMNstc/fSnmHXMdATWM19jDTz7UKDgsE # f6BLrrujpdCEAJM+U100pQA1aWy+nyAlEA0Z+1CQYb45j3qOTfafDh7+B1ESZoMm # GUiVzkrJwX/zOgWb+W/fiH/AI57SHkN6RTHBnE2p8FmyWRnoao0pBAJ3fEtLzXC+ # OrJVWng+vLtvAxAldxU0ivk2zEOS5LpP8WKTKCVXKftRGcehJUBqhFfGsp2xvBwK # 2nxnfn0u6ShMGH7EezFBcZpLKewLPVdQ0srd/Z4FUeVEeN0B3rF1mA1UJP3wTuPi # +IO9crrLPTru8F4XkmhtyGH5pvEqCgulufSe7pgyBYWe6/mDKdPGLH29OncuizdC # oGqC7TtKqpQQpOEN+BfFtlp5MxiS47V1+KHpjgolHuQe8Z9ahyP/n6RRnvs5gBHN # 27XEp6iAb+VT1ODjosLSWxr6MiYtaldwHDykWC6j81tLB9wyWfOHpxptWDGCBG4w # ggRqAgEBMIGQMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNo # ZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRl # ZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWduaW5nIENBAhA5m0DePkFi # npTI8NrwbqMCMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJ # KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB # gjcCARUwLwYJKoZIhvcNAQkEMSIEIDKAQ5nkbX2YbZIl40MLjpz0sIg5HC1twa51 # 2fJkg72gMA0GCSqGSIb3DQEBAQUABIIBAJs+gu3uYXRdzNgynyubf4JCaJH7h8Ui # C762p5QbxcP5K2HNV97vDSaOmek5Oka8MJCF0M9XRtrqgZvWrPoFar5BmdHitoMT # Bz5phn6KLv51w3qlWBfgbPuJ4HU8PyADEDGrH94GwBzcB9lp58jYoDJ8/WAL/7wb # 4O+pwK2ZETCilNb6TEdBMOfPEyLNnWzgVZLvzaXJlDh19I7A1vQjsPks2exJTkgE # 5HH/sf2sI4YvLs6O+cIFgIVgviO/g3Gk6pcBIeBcuH5YS/9JYezfSubi+KeCjZ75 # NsDqylto8Zsgfj5Djge+WbgKBCVx1Ow0nUpGWFRvhZBVE5Lb9Zh8wyyhggIwMIIC # LAYJKoZIhvcNAQkGMYICHTCCAhkCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8G # A1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQQIQ # DUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJAzEL # BgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIxMDMwMzA4NDY0N1owLwYJKoZI # hvcNAQkEMSIEINmOJ4ARDLCVsQMThpC4smjOXbA6O2iSdsxtQNeZkfuvMA0GCSqG # SIb3DQEBAQUABIIBAHvFXI870YIdPfHEKkPA0CBiJi0BHHAOwekSOn7J63vtVIeE # m/xSgvEdg3No+cbWat3CueZqlnlIafTqbDRVLJdMPLRANYAAji+Zsj66UOl5awIX # dUW8mmy9MXM2yDLQhpsMn1EBWjOF0WxCljLHKW2PQolqq15Eh0fqNJnQ2oKJ24hp # qK5AOR90DElei32YzbjSKnS/bhozNed9nCIRnAY4VNM/bfReAO25W8gj5MMqzT3z # tKQyncu2f5X3gt3qAJ4u7Ch/0tZbjGhYQY8pkIGKPFsMI6w2CSksk8X7pDKKYIR4 # sijdXdOJS5F9cd278NL7zzbuwrALC4qB0l1+j/U= # SIG # End signature block |