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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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)
        {
            DumpDGImportParseReport $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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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)"
        }
    }
}

<#
.SYNOPSIS
    Export automation rule configuration from a Cayosoft Administrator Service to a file.
.DESCRIPTION
    Export automation rule configuration from a Cayosoft Administrator Service to a file.
.PARAMETER FileName
    Specifies the output JSON file name.
.PARAMETER Name
    Specifies one or more rule names to export. Supports PowerShell wildcard-expression. When not set, export all rules from the specified container.
.PARAMETER Container
    Specifies one or more names of containers with rules. Supports PowerShell wildcard-expression. When not set, export all rules from Cayosoft Administrator.
.PARAMETER ExcludeRule
    Specifies one or more rule names to exclude from the export. Supports PowerShell wildcard-expression.
.PARAMETER ExcludeContainer
    Specifies one or more names of containers with rules exclude from the export. Supports PowerShell wildcard-expression.
.PARAMETER ConfiguredRulesOnly
    Set to $True to only export configured rules.
.PARAMETER ShowBanner
    If set cmdlet prints version information.
.EXAMPLE
    C:\PS> Export-CGAutomationRule -FileName C:\Temp\output.json -Name "New runbook"
    Description
 
    -----------
     
    This example exports “New runbook” to the JSON file.
.NOTES
    .
#>

function Export-CGAutomationRule
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        [string]$FileName,
         
        [Parameter(Mandatory=$False)]
        [string[]]$Name,
        
        [Parameter(Mandatory=$False)]
        [string[]]$Container,
        
        [Parameter(Mandatory=$False)]
        [string[]]$ExcludeRule,
        
        [Parameter(Mandatory=$False)]
        [string[]]$ExcludeContainer,
        
        [Parameter(Mandatory=$False)]
        [switch]$ConfiguredRulesOnly = $False,
        
        [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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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 =
        @{
            "FileName"=$FileName;
            "Name"=$Name;
            "Containers"=$Container;
            "ExcName"=$ExcludeRule;
            "ExcContainers"=$ExcludeContainer;
            "ConfiguredRulesOnly"=$ConfiguredRulesOnly;
        }
     
        $exported = 0
        
        $err = $null
        try
        {
            $cayoRules = LoadUserRules
            
            $rulesToExport = FilterRules $cayoRules $context
            
            $exported = ExportRulesToFile $rulesToExport $context
        }
        catch
        {
            $err = $_
        }
        
        if ($null -eq $err)
        {
            Log "Export completed successfully. Total exported rules: $($exported)"
        }
        else
        {
            LogError "Export completed with error: $($err)"
        }
    }
}

<#
.SYNOPSIS
    Import automation rule configuration for one or more rule from a file to the Cayosoft Administrator Service.
.DESCRIPTION
    Import automation rule configuration for one or more rule from a file to the Cayosoft Administrator Service.
.PARAMETER FileName
    Specifies the input JSON file name.
.PARAMETER DoNotEnableSchedule
    Set to $True to enable rule schedule after import.
.PARAMETER Overwrite
    Set to $True to overwrite existing rules in the target Cayosoft Administration Service.
.PARAMETER ReportFileName
    Specifies file name for report with details about the operation.
.PARAMETER ShowBanner
    If set cmdlet prints version information.
.EXAMPLE
    C:\PS> Import-CGAutomationRule -Overwrite -DoNotEnableSchedule -FileName C:\Temp\output.json
    Description
 
    -----------
     
    This example imports automation rules from the file to the Cayosoft Administration Service and disables its schedule. If rule exists in the target Service it would be overwritten.
.NOTES
    .
#>

function Import-CGAutomationRule
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        [string]$FileName,
         
        [Parameter(Mandatory=$False)]
        [Switch]$Overwrite,
        
        [Parameter(Mandatory=$False)]
        [Switch]$DoNotEnableSchedule,
        
        [Parameter(Mandatory=$False)]
        [string]$ReportFileName,
        
        [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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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

        $context =
        @{
            "FileName"=$FileName;
            "Overwrite"=$Overwrite;
            "DoNotEnableSchedule"=$DoNotEnableSchedule;
        }
     
        $imported = 0
        
        $err = $null
        try
        {
            $rulesData = LoadRulesFromFile $context
            
            if ($null -ne $rulesData)
            {
                EnsureRulesVersion $rulesData
              
                $imported = ImportRules $rulesData.Items $context
            }
        }
        catch
        {
            $err = $_
            if ($null -ne $rulesData.Items)
            {
                $rulesData.Items | %{ $_.Status = "Failed"; $_.Error = "$($_)" }
            }
        }
        
        if ($null -eq $err -and $null -ne $rulesData)
        {
            try
            {
                $imported = ImportRules $rulesData.Items $context
            }
            catch
            {
                $err = $_
            }
        }
        
        if ([string]::IsNullOrWhiteSpace($ReportFileName) -eq $false)
        {
            DumpAutomationRuleImportParseReport $rulesData.Items $ReportFileName
            Log "Report location: $($ReportFileName)"
        }
        
        if ($null -eq $err)
        {
            Log "Import completed successfully. Total imported rules: $($imported)"
        }
        else
        {
            LogError "Import completed with error: $($err)"
        }
    }
}

<#
.SYNOPSIS
    Deletes automation rule configuration from the Cayosoft Administrator based on input JSON file.
.DESCRIPTION
    Deletes automation rule configuration from the Cayosoft Administrator based on input JSON file.
.PARAMETER FileName
    Specifies input JSON file name contains automation rule configuration to delete.
.PARAMETER ShowBanner
    If set cmdlet prints version information.
.EXAMPLE
    C:\PS> Remove-CGAutomationRule -FileName C:\Temp\output.json
    Description
 
    -----------
     
    This example deletes automation rule configuration specified in the JSON file.
.NOTES
    .
#>

function Remove-CGAutomationRule
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        [string]$FileName,
    
        [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.BuiltinScripts.ModuleIntializer]::Initialize()
        
        $CAModule = "Cayo.PolicyManager.Common.dll"
        if ([string]::IsNullOrWhiteSpace($InstallCAFolder)) { $InstallCAFolder = "C:\Program Files\Cayo Software\AdminAssistant" }
        $CAModulePath = [System.IO.Path]::Combine($InstallCAFolder, $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

        $context =
        @{
            "FileName"=$FileName;
        }
     
        $deleted = 0
        
        $err = $null
        try
        {
            $rulesData = LoadRulesFromFile $context
            
            if ($null -ne $rulesData)
            {
                EnsureRulesVersion $rulesData
              
                $notDeleted = DeleteAutomationRules $rulesData.Items $context
                
                $deleted = $rulesData.Items.Count - $notDeleted.Count
            }
        }
        catch
        {
            $err = $_
        }
        
        if ($null -eq $err)
        {
            Log "Delete completed successfully. Total rules deleted: $($deleted)"
        }
        else
        {
            LogError "Deletion completed with error: $($err)"
        }
    }
}

# SIG # Begin signature block
# MIIp6QYJKoZIhvcNAQcCoIIp2jCCKdYCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBWPxYECfRgMQ9g
# JKK6XILUmRY+tAt/wb+fGPLSblfVXaCCI+EwggVYMIIEQKADAgECAhA5m0DePkFi
# npTI8NrwbqMCMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT
# D1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWdu
# aW5nIENBMB4XDTIwMDcyODAwMDAwMFoXDTIzMDcyODIzNTk1OVowgaExCzAJBgNV
# BAYTAlVTMQ4wDAYDVQQRDAU0MzA4MjENMAsGA1UECAwET2hpbzEUMBIGA1UEBwwL
# V2VzdGVydmlsbGUxLTArBgNVBAkMJDQ3MCBPbGRlIFdvcnRoaW5ndG9uIFJvYWQs
# IFN1aXRlIDIwMDEWMBQGA1UECgwNQ2F5b3NvZnQgSW5jLjEWMBQGA1UEAwwNQ2F5
# b3NvZnQgSW5jLjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbr5AGG
# J8TsPOj1tPgVHQoc99ZNYOChoxPfYdlKlWskyNHf9zOX1lISxqMQ3XbVa2NJ6W0m
# sGr5+KG6kpjC9mS7KT4V9dCCf4e3q+5sf7tqvOgNWF0qizK10W4qD5XW3Z06ZW1Z
# FC70dkI1FwvcCMgtNI+4RoY/kSOX67SV8HkF7VBmnHX2iqLIU+XIPMmmreOv5elY
# vdQ66NjYVkXCv9PNYkMifpS3aqE7Jn4sE5q5lBHnXMpXZ3gNz7YU2vTa38IqBg8d
# 41uQBLxXLJJzAcmODUoydiOaGbfvNHv7UGGjazFSwx0lZj2HwAxhyZaXCgdsyrBR
# W8yS8dWx/PY/gwUCAwEAAaOCAa4wggGqMB8GA1UdIwQYMBaAFA7hOqhTOjHVir7B
# u61nGgOFrTQOMB0GA1UdDgQWBBTyetx3zFkVfM2C6CkRo201vaM7vzAOBgNVHQ8B
# Af8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzARBglg
# hkgBhvhCAQEEBAMCBBAwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAjBggr
# BgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEMGA1Ud
# HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1JTQUNv
# ZGVTaWduaW5nQ0EuY3JsMHMGCCsGAQUFBwEBBGcwZTA+BggrBgEFBQcwAoYyaHR0
# cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdDQS5jcnQw
# IwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMBwGA1UdEQQVMBOB
# EWluZm9AY2F5b3NvZnQuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAgwCcv7GSPMuga
# rwvb4sY9lN5ski3LrSw9CsRt8e9c+CybPGzFPKk1aO+n2CC/GW34KTb0WvQWvB73
# 3cjz/yIeWhtQ8Av427T1uqvNd6vaId060pWNQJBp0lXiuTHd3QdwfuZnewOAl/3A
# fZfD/fJI5+KNmHaKOt0FQ06sFL8u7JF8fPZ6z4kbGIAyMBZJ0qyX3d7Ok6+Sj37b
# V5bcLePYj6RMjECrR6YNOd7DjW69XjHsN03xm2hPqkMNcEkX9OGEgXDqwO0trNMg
# 7hikFoNKO02MrqerlxDPlh2FpDiTKriWI8heMM+9at3RLe74e0M4GFQwslTDe3/F
# 0n0cBkM+MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0B
# AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy
# MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh
# MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAw
# MFoXDTI4MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcg
# SmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJU
# UlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRp
# b24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJl
# FzYOw9sIs9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezco
# EStH2jnGvDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+j
# BvGIGGqQIjy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWm
# p2bIcmfbIWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2u
# TIq3XJq0tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnH
# a4xgk97Exwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWax
# KXwyhGNVicQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjN
# hLixP6Q5D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81
# VXQJSdhJWBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10
# Yy+xUGUJ5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrW
# X1Uu6lzGKAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSME
# GDAWgBSgEQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHY
# m8Cd8rIDZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0g
# BAowCDAGBgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2Rv
# Y2EuY29tL0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgw
# JjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3
# DQEBDAUAA4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+c
# li3vA0p+rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCR
# lv79Q2R+/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHx
# W/BBC5gACiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w5
# 2z97GA1FzZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEU
# xOipakyAvGp4z7h/jnZymQyd/teRCBaho1+VMIIFjTCCBHWgAwIBAgIQDpsYjvnQ
# Lefv21DiCEAYWjANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UE
# ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
# VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAw
# WhcNMzExMTA5MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl
# cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdp
# Q2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
# AoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QN
# xDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DC
# srp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTr
# BcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17l
# Necxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WC
# QTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1
# EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KS
# Op493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAs
# QWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUO
# UlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtv
# sauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCC
# ATYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4c
# D08wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQD
# AgGGMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
# aWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaG
# NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD
# QS5jcmwwEQYDVR0gBAowCDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9D
# XFXnOF+go3QbPbYW1/e/Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6
# Ly23OO/0/4C5+KH38nLeJLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuW
# cqFItJnLnU+nBgMTdydE1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLih
# Vo7spNU96LHc/RzY9HdaXFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBj
# xZgiwbJZ9VVrzyerbHbObyMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02f
# c7cBqZ9Xql4o4rmUMIIF9TCCA92gAwIBAgIQHaJIMG+bJhjQguCWfTPTajANBgkq
# hkiG9w0BAQwFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkx
# FDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
# dHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRo
# b3JpdHkwHhcNMTgxMTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjB8MQswCQYDVQQG
# EwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxm
# b3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxJDAiBgNVBAMTG1NlY3RpZ28g
# UlNBIENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
# ggEBAIYijTKFehifSfCWL2MIHi3cfJ8Uz+MmtiVmKUCGVEZ0MWLFEO2yhyemmcuV
# MMBW9aR1xqkOUGKlUZEQauBLYq798PgYrKf/7i4zIPoMGYmobHutAMNhodxpZW0f
# bieW15dRhqb0J+V8aouVHltg1X7XFpKcAC9o95ftanK+ODtj3o+/bkxBXRIgCFno
# Oc2P0tbPBrRXBbZOoT5Xax+YvMRi1hsLjcdmG0qfnYHEckC14l/vC0X/o84Xpi1V
# sLewvFRqnbyNVlPG8Lp5UEks9wO5/i9lNfIi6iwHr0bZ+UYc3Ix8cSjz/qfGFN1V
# kW6KEQ3fBiSVfQ+noXw62oY1YdMCAwEAAaOCAWQwggFgMB8GA1UdIwQYMBaAFFN5
# v1qqK0rPVIDh2JvAnfKyA2bLMB0GA1UdDgQWBBQO4TqoUzox1Yq+wbutZxoDha00
# DjAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAU
# BggrBgEFBQcDAwYIKwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMFAGA1UdHwRJ
# MEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FD
# ZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2BggrBgEFBQcBAQRqMGgwPwYIKwYB
# BQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FBZGRU
# cnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNv
# bTANBgkqhkiG9w0BAQwFAAOCAgEATWNQ7Uc0SmGk295qKoyb8QAAHh1iezrXMsL2
# s+Bjs/thAIiaG20QBwRPvrjqiXgi6w9G7PNGXkBGiRL0C3danCpBOvzW9Ovn9xWV
# M8Ohgyi33i/klPeFM4MtSkBIv5rCT0qxjyT0s4E307dksKYjalloUkJf/wTr4XRl
# eQj1qZPea3FAmZa6ePG5yOLDCBaxq2NayBWAbXReSnV+pbjDbLXP30p5h1zHQE1j
# NfYw08+1Cg4LBH+gS667o6XQhACTPlNdNKUANWlsvp8gJRANGftQkGG+OY96jk32
# nw4e/gdREmaDJhlIlc5KycF/8zoFm/lv34h/wCOe0h5DekUxwZxNqfBZslkZ6GqN
# KQQCd3xLS81wvjqyVVp4Pry7bwMQJXcVNIr5NsxDkuS6T/FikyglVyn7URnHoSVA
# aoRXxrKdsbwcCtp8Z359LukoTBh+xHsxQXGaSynsCz1XUNLK3f2eBVHlRHjdAd6x
# dZgNVCT98E7j4viDvXK6yz067vBeF5Jobchh+abxKgoLpbn0nu6YMgWFnuv5gynT
# xix9vTp3Los3QqBqgu07SqqUEKThDfgXxbZaeTMYkuO1dfih6Y4KJR7kHvGfWocj
# /5+kUZ77OYARzdu1xKeogG/lU9Tg46LC0lsa+jImLWpXcBw8pFguo/NbSwfcMlnz
# h6cabVgwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEB
# CwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNV
# BAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQg
# Um9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNV
# BAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNl
# cnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3
# qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOW
# bfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt
# 69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3
# YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECn
# wHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6Aa
# RyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTy
# UpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8U
# NM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCON
# WPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBAS
# A31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp61
# 03a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAd
# BgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJx
# XWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF
# BwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
# aWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJo
# dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNy
# bDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQEL
# BQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CK
# Daopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbP
# FXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaH
# bJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxur
# JB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/N
# h4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNB
# zU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77Qpf
# MzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1Oby
# F5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B
# 2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqk
# hQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGwDCCBKig
# AwIBAgIQDE1pckuU+jwqSj0pB4A9WjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQG
# EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0
# IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIy
# MDkyMTAwMDAwMFoXDTMzMTEyMTIzNTk1OVowRjELMAkGA1UEBhMCVVMxETAPBgNV
# BAoTCERpZ2lDZXJ0MSQwIgYDVQQDExtEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMiAt
# IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDP7KUmOsap8mu7jcEN
# mtuh6BSFdDMaJqzQHFUeHjZtvJJVDGH0nQl3PRWWCC9rZKT9BoMW15GSOBwxApb7
# crGXOlWvM+xhiummKNuQY1y9iVPgOi2Mh0KuJqTku3h4uXoW4VbGwLpkU7sqFudQ
# SLuIaQyIxvG+4C99O7HKU41Agx7ny3JJKB5MgB6FVueF7fJhvKo6B332q27lZt3i
# XPUv7Y3UTZWEaOOAy2p50dIQkUYp6z4m8rSMzUy5Zsi7qlA4DeWMlF0ZWr/1e0Bu
# bxaompyVR4aFeT4MXmaMGgokvpyq0py2909ueMQoP6McD1AGN7oI2TWmtR7aeFgd
# Oej4TJEQln5N4d3CraV++C0bH+wrRhijGfY59/XBT3EuiQMRoku7mL/6T+R7Nu8G
# RORV/zbq5Xwx5/PCUsTmFntafqUlc9vAapkhLWPlWfVNL5AfJ7fSqxTlOGaHUQhr
# +1NDOdBk+lbP4PQK5hRtZHi7mP2Uw3Mh8y/CLiDXgazT8QfU4b3ZXUtuMZQpi+ZB
# pGWUwFjl5S4pkKa3YWT62SBsGFFguqaBDwklU/G/O+mrBw5qBzliGcnWhX8T2Y15
# z2LF7OF7ucxnEweawXjtxojIsG4yeccLWYONxu71LHx7jstkifGxxLjnU15fVdJ9
# GSlZA076XepFcxyEftfO4tQ6dwIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeA
# MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkw
# FzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaa
# L3WMaiCPnshvMB0GA1UdDgQWBBRiit7QYfyPMRTtlwvNPSqUFN9SnDBaBgNVHR8E
# UzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcB
# AQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgG
# CCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3
# DQEBCwUAA4ICAQBVqioa80bzeFc3MPx140/WhSPx/PmVOZsl5vdyipjDd9Rk/BX7
# NsJJUSx4iGNVCUY5APxp1MqbKfujP8DJAJsTHbCYidx48s18hc1Tna9i4mFmoxQq
# RYdKmEIrUPwbtZ4IMAn65C3XCYl5+QnmiM59G7hqopvBU2AJ6KO4ndetHxy47JhB
# 8PYOgPvk/9+dEKfrALpfSo8aOlK06r8JSRU1NlmaD1TSsht/fl4JrXZUinRtytIF
# Zyt26/+YsiaVOBmIRBTlClmia+ciPkQh0j8cwJvtfEiy2JIMkU88ZpSvXQJT657i
# nuTTH4YBZJwAwuladHUNPeF5iL8cAZfJGSOA1zZaX5YWsWMMxkZAO85dNdRZPkOa
# GK7DycvD+5sTX2q1x+DzBcNZ3ydiK95ByVO5/zQQZ/YmMph7/lxClIGUgp2sCovG
# SxVK05iQRWAzgOAj3vgDpPZFR+XOuANCR+hBNnF3rf2i6Jd0Ti7aHh2MWsgemtXC
# 8MYiqE+bvdgcmlHEL5r2X6cnl7qWLoVXwGDneFZ/au/ClZpLEQLIgpzJGgV8unG1
# TnqZbPTontRamMifv427GFxD9dAq6OJi7ngE273R+1sKqHB+8JeEeOMIA11HLGOo
# JTiXAdI/Otrl5fbmm9x+LMz/F0xNAKLY1gEOuIvu5uByVYksJxlh9ncBjDGCBV4w
# ggVaAgEBMIGQMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNo
# ZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRl
# ZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWduaW5nIENBAhA5m0DePkFi
# npTI8NrwbqMCMA0GCWCGSAFlAwQCAQUAoHwwEAYKKwYBBAGCNwIBDDECMAAwGQYJ
# KoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQB
# gjcCARUwLwYJKoZIhvcNAQkEMSIEIK7TEJRV7hLobVruNYZFkSHJF8HnrqUiJ6+t
# 0MLMAzMEMA0GCSqGSIb3DQEBAQUABIIBAGojcHSd8hfR2gRJePXjzzDRHK0M/5Cv
# 5zXdBad96v4L0YrOKygZyX9+74BisiAjqMpPgMEkMUgO0z2sQhXJO25ML8JOo9Lc
# ezFFjRSdi3XMLoH+kmvz9y5aDlC4gjN72IsWH86TJNJznGQxDCwan9ifuir5hsFH
# VmDdDfGRh595Rdrf0KthCY0QbHhtO8/WvXazOiVcyAq35U2x+GRY/HTpBlmOEe7R
# lN00Amo9LfddBDUnOIgpXikotw3X4cPaiOWMUegz1hulTzRIBOJ8+XI4f+wi9Rwm
# sGhaGUshAoSjn4WqQK2MBrMr/RqFsdXOFzncY15ZdKYrcJryllUUXQShggMgMIID
# HAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UE
# ChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQg
# UlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAMTWlyS5T6PCpKPSkHgD1a
# MA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkq
# hkiG9w0BCQUxDxcNMjMwNTEyMDkxMDUyWjAvBgkqhkiG9w0BCQQxIgQgO5KIYn/j
# +ACxfLXq5Ug7KLfESYXF/K6/boirzVn4oecwDQYJKoZIhvcNAQEBBQAEggIAEwga
# qhLw53ciRN7TNx+SI8I9m7iRF+CH6zXRebBmc1Z2rfYzACPJa0id4K/jXPXyJWrv
# ceA3l64cIkPx7Qyt1Tw2iczk4m9RL31nM0bw2nYnyTIB3BtoGegxGAWeg7I1gmhP
# xqRN82Yrf5nUSha1peezvuoaFBbXAGQzY5sBDlkw8o5JMqAAY3VnKLV2W/zupEYk
# LgBYv608dHxFfEKwnPsX4i6zhWOhqbvz6SIoKhVJhrlZ/W/o2LppePIc/jxGSyKe
# eXrTHUIzQUgbsCCspx6AV7irXWiudsFBdF/mx7TUaOjBSOJCTjuDzEwGR9R4pRFd
# HJNIZX3bk+iPU4xCIHsHXDj5ODtmX/6Dvi0/EhKO0d/LAiSaPbeCM0w69MDsbWlD
# 76NowYAQ8sWXfJZ8v6Iq5+nXlx0B2uHtCgkM2FXhj37rj4xdQxw+mFXHnXURHjwv
# J4swMy3KvhQQhwOcByS5LnuEV/ZAS5slWKgXGEoVxoTk1qelO5aOsuEtCMIIsY1u
# 8Ydvbaf7wNDIFYpl887jNLqVDR/5U17W2oWKKP3JmoSxPcGpmPNw6lJ+CP1wE+Ts
# FaZsM8mR+2IwS5t8fuR2KeQZGvVAGkI/3eh/E5dNzL3UF6/j1cPRAI/gi3wx0Ndd
# +YvvAEXVrwzz/Q65/uqmqGHD+hMZe4naCK9CseI=
# SIG # End signature block