EPM/Collections.ps1
|
class EpmCollectionInfo { [string]$CollectionUid [string]$CollectionType [string]$Name } function script:Resolve-KeeperEpmCollection { <# .Synopsis Resolve collection(s) by UID or name (case-insensitive). Returns matching collection(s) as an array. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [string] $Identifier, [Parameter(Mandatory = $true)] [object] $Plugin ) $id = $Identifier.Trim() if ([string]::IsNullOrEmpty($id)) { return @() } $collection = $Plugin.Collections.GetEntity($id) if ($null -ne $collection) { return @($collection) } $nameMatches = [System.Collections.Generic.List[object]]::new() foreach ($c in @($Plugin.Collections.GetAll() | Where-Object { $null -ne $_ })) { if (-not $c.CollectionData -or $c.CollectionData.Length -eq 0) { continue } try { $jsonStr = [System.Text.Encoding]::UTF8.GetString($c.CollectionData) $data = $jsonStr | ConvertFrom-Json if ($data.PSObject.Properties['Name'] -and $data.Name -and $data.Name.Equals($id, [System.StringComparison]::OrdinalIgnoreCase)) { $nameMatches.Add($c) } } catch { Write-Debug "Failed to parse CollectionData for $($c.CollectionUid): $($_.Exception.Message)" } } return @($nameMatches) } function script:Resolve-KeeperEpmSingleCollection { <# .Synopsis Resolve a single collection by UID or name. Errors if not found or not unique. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true)][string] $Identifier, [Parameter(Mandatory = $true)][object] $Plugin ) [array]$collections = @(Resolve-KeeperEpmCollection -Identifier $Identifier -Plugin $Plugin | Where-Object { $null -ne $_ }) if ($collections.Count -eq 0) { Write-Error -Message "Collection '$Identifier' not found." -ErrorAction Stop } if ($collections.Count -gt 1) { Write-Warning "Multiple collections found with name `"$Identifier`":" foreach ($c in $collections) { $name = Get-KeeperEpmCollectionName -Collection $c Write-Warning " UID: $($c.CollectionUid) Name: $name" } Write-Error -Message "Collection name `"$Identifier`" is not unique. Use Collection UID." -ErrorAction Stop } return $collections[0] } function script:Get-KeeperEpmCollectionName { Param ([object] $Collection) if (-not $Collection.CollectionData -or $Collection.CollectionData.Length -eq 0) { return '' } try { $jsonStr = [System.Text.Encoding]::UTF8.GetString($Collection.CollectionData) $data = $jsonStr | ConvertFrom-Json if ($data.PSObject.Properties['Name'] -and $data.Name) { return [string]$data.Name } } catch { Write-Debug "Failed to parse CollectionData: $($_.Exception.Message)" } return '' } function script:ConvertFrom-KeeperEpmLinkType { Param ([string] $LinkType) $v = $LinkType.Trim().ToLowerInvariant() switch ($v) { 'agent' { return [int][PEDM.CollectionLinkType]::CltAgent } 'policy' { return [int][PEDM.CollectionLinkType]::CltPolicy } 'collection' { return [int][PEDM.CollectionLinkType]::CltCollection } default { return $null } } } function Get-KeeperEpmCollectionList { <# .Synopsis List all EPM collections. .Parameter CollectionType Optional collection type number to filter results (1=OS Build, 2=Application, 3=User Account, 4=Group Account, 202=OS Version). #> [CmdletBinding()] Param ( [Parameter()] [int] $CollectionType = -1 ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $hasTypeFilter = $PSBoundParameters.ContainsKey('CollectionType') if ($hasTypeFilter) { [array]$collections = @($plugin.Collections.GetAll() | Where-Object { $null -ne $_ -and $_.CollectionType -eq $CollectionType } | Sort-Object -Property CollectionType, CollectionUid) } else { [array]$collections = @($plugin.Collections.GetAll() | Where-Object { $null -ne $_ } | Sort-Object -Property CollectionType, CollectionUid) } if ($collections.Count -eq 0) { Write-Output "No collections found." return } $rows = [System.Collections.Generic.List[EpmCollectionInfo]]::new() foreach ($coll in $collections) { $typeName = getEpmCollectionTypeName -CollectionType $coll.CollectionType $name = Get-KeeperEpmCollectionName -Collection $coll $row = [EpmCollectionInfo]::new() $row.CollectionUid = $coll.CollectionUid $row.CollectionType = $typeName $row.Name = $name $rows.Add($row) } $rows | Format-Table -AutoSize } function Get-KeeperEpmCollection { <# .Synopsis View a single EPM collection by UID or name. .Parameter CollectionUidOrName Collection UID or name (case-insensitive). #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string] $CollectionUidOrName ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collection = Resolve-KeeperEpmSingleCollection -Identifier $CollectionUidOrName -Plugin $plugin $created = [DateTimeOffset]::FromUnixTimeMilliseconds($collection.Created).ToString("yyyy-MM-dd HH:mm:ss") Write-Output "Collection: $($collection.CollectionUid)" Write-Output " Type: $(getEpmCollectionTypeName -CollectionType $collection.CollectionType)" Write-Output " Created: $created" if ($collection.CollectionData -and $collection.CollectionData.Length -gt 0) { try { $jsonStr = [System.Text.Encoding]::UTF8.GetString($collection.CollectionData) $data = $jsonStr | ConvertFrom-Json if ($data.PSObject.Properties['Name'] -and $data.Name) { Write-Output " Name: $($data.Name)" } foreach ($prop in $data.PSObject.Properties) { if ($prop.Name -eq 'Name') { continue } $val = $prop.Value if ($val -is [System.Management.Automation.PSCustomObject]) { Write-Output " $($prop.Name):" foreach ($inner in $val.PSObject.Properties) { Write-Output " $($inner.Name): $($inner.Value)" } } elseif ($val -is [System.Collections.IEnumerable] -and $val -isnot [string]) { Write-Output " $($prop.Name): [$($val -join ', ')]" } else { Write-Output " $($prop.Name): $val" } } } catch { try { $dataJson = [System.Text.Encoding]::UTF8.GetString($collection.CollectionData) Write-Output " Data: $dataJson" } catch { Write-Output " Data: (binary data, $($collection.CollectionData.Length) bytes)" } } } [array]$links = @($plugin.CollectionLinks.GetLinksForSubject($collection.CollectionUid) | Where-Object { $null -ne $_ }) $agentLinkType = [int][PEDM.CollectionLinkType]::CltAgent [array]$agentLinks = @($links | Where-Object { $_.LinkType -eq $agentLinkType }) if ($agentLinks.Count -gt 0) { Write-Output "" Write-Output " Linked Agents ($($agentLinks.Count)):" foreach ($link in $agentLinks) { $agent = $plugin.Agents.GetEntity($link.LinkUid) if ($agent) { $machineName = if ($agent.MachineId) { $agent.MachineId } else { '(unknown)' } Write-Output " $($link.LinkUid) ($machineName)" } else { Write-Output " $($link.LinkUid)" } } } else { Write-Output "" Write-Output " Linked Agents: (none)" } $policyLinkType = [int][PEDM.CollectionLinkType]::CltPolicy [array]$policyLinks = @($links | Where-Object { $_.LinkType -eq $policyLinkType }) if ($policyLinks.Count -gt 0) { Write-Output "" Write-Output " Linked Policies ($($policyLinks.Count)):" foreach ($link in $policyLinks) { Write-Output " $($link.LinkUid)" } } $collLinkType = [int][PEDM.CollectionLinkType]::CltCollection [array]$collLinks = @($links | Where-Object { $_.LinkType -eq $collLinkType }) if ($collLinks.Count -gt 0) { Write-Output "" Write-Output " Linked Collections ($($collLinks.Count)):" foreach ($link in $collLinks) { $linkedColl = $plugin.Collections.GetEntity($link.LinkUid) if ($linkedColl) { $linkedName = Get-KeeperEpmCollectionName -Collection $linkedColl if ($linkedName) { Write-Output " $($link.LinkUid) ($linkedName)" } else { Write-Output " $($link.LinkUid)" } } else { Write-Output " $($link.LinkUid)" } } } } function Add-KeeperEpmCollection { <# .Synopsis Add a new EPM collection. .Parameter CollectionUid Optional collection UID. If omitted, one is generated automatically. .Parameter CollectionType Collection type (required). 1=OS Build, 2=Application, 3=User Account, 4=Group Account, 202=OS Version. .Parameter Data Collection data as a JSON string. .Parameter DataFile Path to a file containing collection data JSON. #> [CmdletBinding()] Param ( [Parameter(Position = 0)] [string] $CollectionUid, [Parameter(Mandatory = $true)] [int] $CollectionType, [Parameter()] [string] $Data, [Parameter()] [string] $DataFile ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collUid = if ($CollectionUid) { $CollectionUid.Trim() } if ([string]::IsNullOrEmpty($collUid)) { $collUid = [KeeperSecurity.Utils.CryptoUtils]::GenerateUid() Write-Output "Generated Collection UID: $collUid" } if ($CollectionType -eq 0) { Write-Error -Message "Collection type is required for 'add' command. Use -CollectionType (e.g., 2 for Application)." -ErrorAction Stop } $dataJson = readEpmJsonText -Json $Data -FilePath $DataFile if ([string]::IsNullOrEmpty($dataJson)) { $dataJson = '{}' } $collectionData = New-Object KeeperSecurity.Plugins.EPM.CollectionData $collectionData.CollectionUid = $collUid $collectionData.CollectionType = $CollectionType $collectionData.CollectionDataJson = $dataJson try { $addStatus = $plugin.ModifyCollections( [KeeperSecurity.Plugins.EPM.CollectionData[]]@($collectionData), $null, $null ).GetAwaiter().GetResult() if ($addStatus.AddErrors -and $addStatus.AddErrors.Count -gt 0) { $err = $addStatus.AddErrors[0] Write-Error -Message "Failed to add collection `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Stop } if ($addStatus.Add -and $addStatus.Add.Count -gt 0) { Write-Output "Collection '$collUid' added." } else { Write-Warning "No collection was added. Check server response." } writeEpmModifyStatus -Status $addStatus $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error adding collection: $($_.Exception.Message)" -ErrorAction Stop } } function Update-KeeperEpmCollection { <# .Synopsis Update an existing EPM collection. .Parameter CollectionUidOrName Collection UID or name (case-insensitive). .Parameter CollectionType New collection type (optional). If omitted, keeps existing type. .Parameter Data Collection data as a JSON string. .Parameter DataFile Path to a file containing collection data JSON. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string] $CollectionUidOrName, [Parameter()] [int] $CollectionType = -1, [Parameter()] [string] $Data, [Parameter()] [string] $DataFile ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collection = Resolve-KeeperEpmSingleCollection -Identifier $CollectionUidOrName -Plugin $plugin $dataJson = readEpmJsonText -Json $Data -FilePath $DataFile if ([string]::IsNullOrEmpty($dataJson)) { if ($collection.CollectionData -and $collection.CollectionData.Length -gt 0) { $dataJson = [System.Text.Encoding]::UTF8.GetString($collection.CollectionData) } else { $dataJson = '{}' } } $typeValue = if ($PSBoundParameters.ContainsKey('CollectionType') -and $CollectionType -ne 0) { $CollectionType } else { $collection.CollectionType } $collectionData = New-Object KeeperSecurity.Plugins.EPM.CollectionData $collectionData.CollectionUid = $collection.CollectionUid $collectionData.CollectionType = $typeValue $collectionData.CollectionDataJson = $dataJson try { $updateStatus = $plugin.ModifyCollections( $null, [KeeperSecurity.Plugins.EPM.CollectionData[]]@($collectionData), $null ).GetAwaiter().GetResult() if ($updateStatus.UpdateErrors -and $updateStatus.UpdateErrors.Count -gt 0) { $err = $updateStatus.UpdateErrors[0] Write-Error -Message "Failed to update collection `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Stop } if ($updateStatus.Update -and $updateStatus.Update.Count -gt 0) { Write-Output "Collection '$($collection.CollectionUid)' updated." } else { Write-Warning "No collection was updated. Check server response." } writeEpmModifyStatus -Status $updateStatus $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error updating collection: $($_.Exception.Message)" -ErrorAction Stop } } function Remove-KeeperEpmCollection { <# .Synopsis Remove an EPM collection by UID or name. .Parameter CollectionUidOrName Collection UID or name (case-insensitive). .Parameter Force If set, skip confirmation prompt before delete. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] Param ( [Parameter(Mandatory = $true, Position = 0)] [string] $CollectionUidOrName, [Parameter()] [switch] $Force ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collection = Resolve-KeeperEpmSingleCollection -Identifier $CollectionUidOrName -Plugin $plugin $collName = Get-KeeperEpmCollectionName -Collection $collection $displayName = if ($collName) { $collName } else { $collection.CollectionUid } if (-not $Force -and -not $PSCmdlet.ShouldProcess("collection '$displayName'", "Delete")) { return } try { $removeStatus = $plugin.ModifyCollections( $null, $null, [string[]]@($collection.CollectionUid) ).GetAwaiter().GetResult() if ($removeStatus.RemoveErrors -and $removeStatus.RemoveErrors.Count -gt 0) { $err = $removeStatus.RemoveErrors[0] Write-Error -Message "Failed to remove collection `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Stop } if ($removeStatus.Remove -and $removeStatus.Remove.Count -gt 0) { Write-Output "Collection '$($collection.CollectionUid)' removed." } else { Write-Warning "No collection was removed. Check server response." } writeEpmModifyStatus -Status $removeStatus $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error removing collection: $($_.Exception.Message)" -ErrorAction Stop } } function Connect-KeeperEpmCollection { <# .Synopsis Link a collection to agent(s), policy(ies), or other collection(s). .Parameter CollectionUidOrName Collection UID or name (case-insensitive). .Parameter LinkType Type of link: agent, policy, or collection. .Parameter LinkUid One or more UIDs or names to link. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, Position = 0)] [string] $CollectionUidOrName, [Parameter(Mandatory = $true)] [ValidateSet('agent', 'policy', 'collection')] [string] $LinkType, [Parameter(Mandatory = $true)] [string[]] $LinkUid ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collection = Resolve-KeeperEpmSingleCollection -Identifier $CollectionUidOrName -Plugin $plugin $linkTypeValue = ConvertFrom-KeeperEpmLinkType -LinkType $LinkType $links = [System.Collections.Generic.List[string]]::new() foreach ($uid in $LinkUid) { $trimmed = if ($uid) { $uid.Trim() } if ([string]::IsNullOrEmpty($trimmed)) { continue } switch ($linkTypeValue) { ([int][PEDM.CollectionLinkType]::CltAgent) { [array]$agentMatches = @(Resolve-KeeperEpmAgent -Identifier $trimmed -Plugin $plugin | Where-Object { $null -ne $_ }) if ($agentMatches.Count -eq 0) { Write-Warning "Agent '$trimmed' not found." continue } if ($agentMatches.Count -gt 1) { Write-Warning "Multiple agents match name '$trimmed'. Use Agent UID." continue } $links.Add($agentMatches[0].AgentUid) } ([int][PEDM.CollectionLinkType]::CltPolicy) { [array]$policyMatches = @(Resolve-KeeperEpmPolicy -Identifier $trimmed -Plugin $plugin | Where-Object { $null -ne $_ }) if ($policyMatches.Count -eq 0) { Write-Warning "Policy '$trimmed' not found." continue } if ($policyMatches.Count -gt 1) { Write-Warning "Multiple policies match name '$trimmed'. Use Policy UID." continue } $links.Add($policyMatches[0].PolicyUid) } ([int][PEDM.CollectionLinkType]::CltCollection) { [array]$collMatches = @(Resolve-KeeperEpmCollection -Identifier $trimmed -Plugin $plugin | Where-Object { $null -ne $_ }) if ($collMatches.Count -eq 0) { Write-Warning "Collection '$trimmed' not found." continue } if ($collMatches.Count -gt 1) { Write-Warning "Multiple collections match name '$trimmed'. Use Collection UID." continue } $links.Add($collMatches[0].CollectionUid) } } } if ($links.Count -eq 0) { Write-Error -Message "No valid links found." -ErrorAction Stop } $setLinks = [System.Collections.Generic.List[KeeperSecurity.Plugins.EPM.CollectionLink]]::new() foreach ($linkUidValue in $links) { $cl = New-Object KeeperSecurity.Plugins.EPM.CollectionLink $cl.CollectionUid = $collection.CollectionUid $cl.LinkUid = $linkUidValue $cl.LinkType = $linkTypeValue $setLinks.Add($cl) } try { $status = $plugin.SetCollectionLinks($setLinks, $null).GetAwaiter().GetResult() $hasErrors = $false if ($status.AddErrors -and $status.AddErrors.Count -gt 0) { foreach ($err in $status.AddErrors) { Write-Error -Message "Failed to connect collection link `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Continue $hasErrors = $true } } if ($status.Add -and $status.Add.Count -gt 0) { Write-Output "$($status.Add.Count) link(s) connected." } elseif (-not $hasErrors) { Write-Warning "No links were connected. Check server response." } writeEpmModifyStatus -Status $status $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error connecting collection: $($_.Exception.Message)" -ErrorAction Stop } } function Disconnect-KeeperEpmCollection { <# .Synopsis Unlink agent(s), policy(ies), or collection(s) from a collection. .Parameter CollectionUidOrName Collection UID or name (case-insensitive). .Parameter LinkUid One or more link UIDs to disconnect. .Parameter Force Skip confirmation prompt. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] Param ( [Parameter(Mandatory = $true, Position = 0)] [string] $CollectionUidOrName, [Parameter(Mandatory = $true)] [string[]] $LinkUid, [Parameter()] [switch] $Force ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } $collection = Resolve-KeeperEpmSingleCollection -Identifier $CollectionUidOrName -Plugin $plugin [array]$existingLinks = @($plugin.CollectionLinks.GetLinksForSubject($collection.CollectionUid) | Where-Object { $null -ne $_ }) $toUnlink = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase) foreach ($u in $LinkUid) { $t = if ($u) { $u.Trim() } if (-not [string]::IsNullOrEmpty($t)) { $toUnlink.Add($t) | Out-Null } } $unsetLinks = [System.Collections.Generic.List[KeeperSecurity.Plugins.EPM.CollectionLink]]::new() foreach ($link in $existingLinks) { if ($toUnlink.Contains($link.LinkUid)) { $cl = New-Object KeeperSecurity.Plugins.EPM.CollectionLink $cl.CollectionUid = $collection.CollectionUid $cl.LinkUid = $link.LinkUid $cl.LinkType = $link.LinkType $unsetLinks.Add($cl) $toUnlink.Remove($link.LinkUid) | Out-Null } } if ($toUnlink.Count -gt 0) { Write-Warning "$($toUnlink.Count) link(s) cannot be removed from collection: $CollectionUidOrName" } if ($unsetLinks.Count -eq 0) { return } if (-not $Force -and -not $PSCmdlet.ShouldProcess("$($unsetLinks.Count) link(s) from collection '$CollectionUidOrName'", "Disconnect")) { return } try { $status = $plugin.SetCollectionLinks($null, $unsetLinks).GetAwaiter().GetResult() $hasErrors = $false if ($status.RemoveErrors -and $status.RemoveErrors.Count -gt 0) { foreach ($err in $status.RemoveErrors) { Write-Error -Message "Failed to disconnect collection link `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Continue $hasErrors = $true } } if ($status.Remove -and $status.Remove.Count -gt 0) { Write-Output "$($status.Remove.Count) link(s) disconnected." } elseif (-not $hasErrors) { Write-Warning "No links were disconnected. Check server response." } writeEpmModifyStatus -Status $status $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error disconnecting collection: $($_.Exception.Message)" -ErrorAction Stop } } function Remove-KeeperEpmCollectionsByType { <# .Synopsis Remove all EPM collections of a given type (wipe-out). .Parameter CollectionType Collection type to wipe (1=OS Build, 2=Application, 3=User Account, 4=Group Account, 202=OS Version). .Parameter Force Skip confirmation prompt. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] Param ( [Parameter(Mandatory = $true, Position = 0)] [int] $CollectionType, [Parameter()] [switch] $Force ) $plugin = ensureEpmPlugin if (-not $plugin) { Write-Error -Message "EPM plugin is not available. Enterprise admin access is required." -ErrorAction Stop } [array]$collectionUids = @($plugin.Collections.GetAll() | Where-Object { $null -ne $_ -and $_.CollectionType -eq $CollectionType } | ForEach-Object { $_.CollectionUid }) if ($collectionUids.Count -eq 0) { $typeName = getEpmCollectionTypeName -CollectionType $CollectionType Write-Output "No collections found for type: $typeName ($CollectionType)" return } $typeName = getEpmCollectionTypeName -CollectionType $CollectionType if (-not $Force -and -not $PSCmdlet.ShouldProcess("$($collectionUids.Count) $typeName collection(s)", "Delete")) { return } try { $removeStatus = $plugin.ModifyCollections( $null, $null, [string[]]$collectionUids ).GetAwaiter().GetResult() $hasErrors = $false if ($removeStatus.RemoveErrors -and $removeStatus.RemoveErrors.Count -gt 0) { foreach ($err in $removeStatus.RemoveErrors) { if (-not $err.Success) { Write-Error -Message "Failed to remove collection `"$($err.EntityUid)`": $($err.Message)" -ErrorAction Continue $hasErrors = $true } } } if ($removeStatus.Remove -and $removeStatus.Remove.Count -gt 0) { Write-Output "$($removeStatus.Remove.Count) collection(s) removed." } elseif (-not $hasErrors) { Write-Warning "No collections were removed. Check server response." } writeEpmModifyStatus -Status $removeStatus $plugin.SyncDown($false).GetAwaiter().GetResult() | Out-Null } catch { Write-Error -Message "Error removing collections: $($_.Exception.Message)" -ErrorAction Stop } } New-Alias -Name kepm-collection-list -Value Get-KeeperEpmCollectionList -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-view -Value Get-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-add -Value Add-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-edit -Value Update-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-delete -Value Remove-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-connect -Value Connect-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-disconnect -Value Disconnect-KeeperEpmCollection -ErrorAction SilentlyContinue New-Alias -Name kepm-collection-wipeout -Value Remove-KeeperEpmCollectionsByType -ErrorAction SilentlyContinue # SIG # Begin signature block # MIInvgYJKoZIhvcNAQcCoIInrzCCJ6sCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCoxZVCUH5fMS2Q # drXUdA9qOuo9fqwbF1YRArAYY/W74aCCITswggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0GCSqG # SIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTlaMGkx # CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4 # RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEzODQg # MjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C0Cit # eLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce2vnS # 1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0daE6ZM # swEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6TSXBC # Mo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoAFdE3 # /hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7OhD26j # q22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM1bL5 # OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z8ujo # 7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05huzU # tw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNYmtwm # KwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP/2NP # TLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0TAQH/ # BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYDVR0j # BBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8E # PDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz # dGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATANBgkq # hkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95RysQDK # r2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HLIvda # qpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5BtfQ/g+ # lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnhOE7a # brs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIhdXNS # y0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV9zeK # iwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/jwVYb # KyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYHKi8Q # xAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmCXBVm # zGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l/aCn # HwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZWeE4w # gga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0GCSqGSIb3DQEBCwUAMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTlaMGkxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1 # c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEwggIi # MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHTCphBcr48RsAcrHXbo0Zo # dLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPhof6pvF4uGjwjqNjfEvUi # 6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mAxAHeHYNnQxqXmRinvuNg # xVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBvMgEdgkFiDNYiOTx4OtiF # cMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps0wjUjsZvkgFkriK9tUKJ # m/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF83bRVFLeGkuAhHiGPMvS # GmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXiUOeSLsJygoLPp66bkDX1 # ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOMCZIVNSaz7BX8VtYGqLt9 # MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydPpOjL6s36czwzsucuoKs7 # Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrUG2ZdSoQbU2rMkpLiQ6bG # RinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+sdFUeEY0qVjPKOWug/G6 # X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAd # BgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYDVR0jBBgwFoAU7NfjgtJx # XWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF # BwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln # aWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJo # dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNy # bDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQEL # BQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WIGjB/T8ObXAZz8OjuhUxj # aaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+IQhQE7jU/kXjjytJgnn0 # hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8Myb9rEVKChHyfpzee5kH0 # F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2th9y1IsA0QF8dTXqvcnT # mpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjajV/gxdEkMx1NKU4uHQcKf # ZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2Lr3ty9qIijanrUR3anzE # wlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFzeGxcytL5TTLL4ZaoBdqbh # OhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG7uEBYTptMSbhdhGQDpOX # gpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+NJpud/v4+7RWsWCiKi9EO # LLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckTetiSuEtQvLsNz3Qbp7wG # WqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszWkPZPubdcMIIG7TCCBNWg # AwIBAgIQCoDvGEuN8QWC0cR2p5V0aDANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQG # EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0 # IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUgQ0Ex # MB4XDTI1MDYwNDAwMDAwMFoXDTM2MDkwMzIzNTk1OVowYzELMAkGA1UEBhMCVVMx # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBTSEEy # NTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIwMjUgMTCCAiIwDQYJKoZI # hvcNAQEBBQADggIPADCCAgoCggIBANBGrC0Sxp7Q6q5gVrMrV7pvUf+GcAoB38o3 # zBlCMGMyqJnfFNZx+wvA69HFTBdwbHwBSOeLpvPnZ8ZN+vo8dE2/pPvOx/Vj8Tch # TySA2R4QKpVD7dvNZh6wW2R6kSu9RJt/4QhguSssp3qome7MrxVyfQO9sMx6ZAWj # FDYOzDi8SOhPUWlLnh00Cll8pjrUcCV3K3E0zz09ldQ//nBZZREr4h/GI6Dxb2Uo # yrN0ijtUDVHRXdmncOOMA3CoB/iUSROUINDT98oksouTMYFOnHoRh6+86Ltc5zjP # KHW5KqCvpSduSwhwUmotuQhcg9tw2YD3w6ySSSu+3qU8DD+nigNJFmt6LAHvH3KS # uNLoZLc1Hf2JNMVL4Q1OpbybpMe46YceNA0LfNsnqcnpJeItK/DhKbPxTTuGoX7w # JNdoRORVbPR1VVnDuSeHVZlc4seAO+6d2sC26/PQPdP51ho1zBp+xUIZkpSFA8vW # doUoHLWnqWU3dCCyFG1roSrgHjSHlq8xymLnjCbSLZ49kPmk8iyyizNDIXj//cOg # rY7rlRyTlaCCfw7aSUROwnu7zER6EaJ+AliL7ojTdS5PWPsWeupWs7NpChUk555K # 096V1hE0yZIXe+giAwW00aHzrDchIc2bQhpp0IoKRR7YufAkprxMiXAJQ1XCmnCf # gPf8+3mnAgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTkO/zy # Me39/dfzkXFjGVBDz2GM6DAfBgNVHSMEGDAWgBTvb1NK6eQGfHrK4pBW9i/USezL # TjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwgZUGCCsG # AQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j # b20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZTSEEyNTYyMDI1Q0ExLmNy # dDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln # aUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5j # cmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEB # CwUAA4ICAQBlKq3xHCcEua5gQezRCESeY0ByIfjk9iJP2zWLpQq1b4URGnwWBdEZ # D9gBq9fNaNmFj6Eh8/YmRDfxT7C0k8FUFqNh+tshgb4O6Lgjg8K8elC4+oWCqnU/ # ML9lFfim8/9yJmZSe2F8AQ/UdKFOtj7YMTmqPO9mzskgiC3QYIUP2S3HQvHG1FDu # +WUqW4daIqToXFE/JQ/EABgfZXLWU0ziTN6R3ygQBHMUBaB5bdrPbF6MRYs03h4o # bEMnxYOX8VBRKe1uNnzQVTeLni2nHkX/QqvXnNb+YkDFkxUGtMTaiLR9wjxUxu2h # ECZpqyU1d0IbX6Wq8/gVutDojBIFeRlqAcuEVT0cKsb+zJNEsuEB7O7/cuvTQasn # M9AWcIQfVjnzrvwiCZ85EE8LUkqRhoS3Y50OHgaY7T/lwd6UArb+BOVAkg2oOvol # /DJgddJ35XTxfUlQ+8Hggt8l2Yv7roancJIFcbojBcxlRcGG0LIhp6GvReQGgMgY # xQbV1S3CrWqZzBt1R9xJgKf47CdxVRd/ndUlQ05oxYy2zRWVFjF7mcr4C34Mj3oc # CVccAvlKV9jEnstrniLvUxxVZE/rptb7IRE2lskKPIJgbaP5t2nGj/ULLi49xTcB # ZU8atufk+EMF/cWuiC7POGT75qaL6vdCvHlshtjdNXOCIUjsarfNZzCCB0kwggUx # oAMCAQICEAe0P3SLJmcoVNrErUyxTt0wDQYJKoZIhvcNAQELBQAwaTELMAkGA1UE # BhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2Vy # dCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENB # MTAeFw0yNTEyMzEwMDAwMDBaFw0yOTAxMDIyMzU5NTlaMIHRMRMwEQYLKwYBBAGC # NzwCAQMTAlVTMRkwFwYLKwYBBAGCNzwCAQITCERlbGF3YXJlMR0wGwYDVQQPDBRQ # cml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMzQwNzk4NTELMAkGA1UEBhMC # VVMxETAPBgNVBAgTCElsbGlub2lzMRAwDgYDVQQHEwdDaGljYWdvMR0wGwYDVQQK # ExRLZWVwZXIgU2VjdXJpdHkgSW5jLjEdMBsGA1UEAxMUS2VlcGVyIFNlY3VyaXR5 # IEluYy4wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCUcNMoSVmxAi0a # vG+StFJMNFFTUIOo3HdBZ+0gqA1XpNgUx11vB1vCZrvFsD9m5oA58tdp4gZN3LmQ # aMvCl2ANUT7MilI02Hf1RWlygBzon6iE0GpU3lgRrwrk1dhtLpGsR6dbMKUUHprc # vKpXk90/VN+vhzY1uik1tCTxkDCPu/AYJg7m9+tR2KqvMuYMaMLhii66eWUAGsBC # h/uZxjkGoJF6qZ0DgFd7rW7VYljbfYSNPeZNGTDgB0J/wOsKl0mn612DTseIvAKt # 4vra/FLFukyEyStnfQ8lWYDcLLCMCjNVrzGipmT5E2iyx7Y1RZCIpNwVogp3Ixbk # Gbq5A/41YNOLLd4cFewyB2F037RevBCRsUODZEt1qBf7Jbu3DiYo1G+zTj9E0R1s # FzyijcfdsTm6X5ble+yCJeGkX5XgsyPnZpyz/FX9Fr0N9pMPGWwW2PKyHEnSytXm # 0Dxdq2P4mA4CBUxq7YoV26L2PF6QEh9BQdXTPcnLysUv7SI/a0ECAwEAAaOCAgIw # ggH+MB8GA1UdIwQYMBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBRG # 4H6CH8pvNX632bsdnrda4MtJLDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYB # BQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMC # B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25p # bmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI # QTM4NDIwMjFDQTEuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JT # QTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA # A4ICAQA1Wlq0WzJa3N6DgjgBU7nagIJBab1prPARXZreX1MOv9VjnS5o0CrfQLr6 # z3bmWHw7xT8dt6bcSwRixqvPJtv4q8Rvo80O3eUMvMxQzqmi7z1zf+HG+/3G4F+2 # IYegvPc8Ui151XCV9rjA8tvFWRLRMX0ZRxY1zfT027HMw0iYL20z44+Cky//FAnL # iRwoNDGiRkZiHbB9YOftPAYNMG3gm1z3zOW5RdfKPrqvMuijE+dfyLIAA6Immpzu # FMH+Wgn8NnSlot9b4YKycaqqdjd7wXDjPub/oQ7VShuCSBWj+UNOTVh0vcZGackc # H1DLVgwp2dcKlxJiQKtkHT/T6LloY6LTe6+8wkVkr8EAv1W+q/+M1a4Ao+ykFbIA # 2LBEmA9qdgoLtenAYIiEg+48SjMPgyBbVPE3bhL1vIqjEIxYCfdmi6wx33oYX7HB # +bJ7zitHw4GgtpfPV8y8QRZImKmeDOKyXjQPDmQM/Eglm/Ns0GzBkVXM8h6UI34b # WZrHz9sbLSE20m5Svmxftvw5zju+I3WsmS/stNfWlOkwU0niUgwPHaz21kjXEA5A # g+aqv26wodqZcnGOlChoWDvSJ8KKgdOFbeAYKAMp1NY7iWV315zpGH19RipCR1NH # 0ND8iIubk3WGNf2rzEfqlOi3h2ywqVkU6AKXHdO5JV4otSKKEDGCBdkwggXVAgEB # MH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYD # VQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNI # QTM4NCAyMDIxIENBMQIQB7Q/dIsmZyhU2sStTLFO3TANBglghkgBZQMEAgEFAKCB # hDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE # AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJ # BDEiBCCKOy5s0QstUCtT13hT1N0s9Z1AwwC8eRvelS5/4LZOCjANBgkqhkiG9w0B # AQEFAASCAYB4JMX5duU1tU/a0zp0RRUTJ0OOehnTemdoNFkcUZmTI5QrzKdEmY0/ # CFumeUJYz4zxSs7qZnA4rq4sFHX3s959EFaQWnFKhznuKccxB1xEh3pITGEkZx2t # Kkpg9XJ0Z2RifkpgoXcnXS28jJ6djJbYw6862TjXdjkfQ9ZohfRWDGiizEkkH/Oj # FSd1A7S2p2iHKUUhSoChzdA+qK6wV1z/RXvZ80tIp++Fb51y+YfvTTLZU4t4y7E5 # dHyT+5PAXgGPGVnBDbFgsg3lyHaGIbbzZvHLY2AyZdiCijxDrV9GS/H6FOGH+UN0 # h7MYsl0A4U38H+UPFdZhRojrtyt4pJN7FZkZkcoUd0nZt7J7q17y2rElokR4oYsP # DBCNVHS6vRcm3uhI3OQcWVZCo7EflSAQyrlFDnCJY542esEMnuBWMTDUYCvGPcMO # 0vzqdS+B1ZF9nSAsp+nwo6kA7xSN5vK3+YO1ZPwqKl9YUlvucgCI4TEn0TE6MPmc # 2Sg3R2uPN8ihggMmMIIDIgYJKoZIhvcNAQkGMYIDEzCCAw8CAQEwfTBpMQswCQYD # VQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lD # ZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hBMjU2IDIwMjUg # Q0ExAhAKgO8YS43xBYLRxHanlXRoMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcN # AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjYwNTI2MDQwNjQ2WjAv # BgkqhkiG9w0BCQQxIgQg0Bsi1C//wZp9cPBcCeGntLSVnKbeJG826AtEGFbaI1Aw # DQYJKoZIhvcNAQEBBQAEggIAr3/bmjeQ2XAUE3KExQ+H6YAGsEHZS3b3hMR2Azi5 # 8vJ8qW/qEu7ENtusVq5eBo6U6Gk04Ron9G8Qp+MWJu6WHd+WOoG07M0swmO65Vbt # 21isoRkqbSbbW/NGNkjiMxY6O3B66GhT/CpDA4vgDqCo8WEIxHiMSHDgjfadXFof # Q5RJiA46oZH8OfOXAW9mJlol5XnVXOBtxNsFbUfqbqCChb6rlxZ/7oZQSY/UTxV6 # 1TB8AQQrDTO5l+YBYD+UwWhUzX1NrAcY2YYVQ8Gs8E2RIDoCk0bMzUeKzbZUsQ/q # LR4vCuW9umOjDwxwJAw+XDvlOcRrjB9hK5zzslERGQN/9NlzFxlAvFRzyrh4h9Ku # GgXtcskvl7hJMbXD3pyrlhE6vrB1JqkUnJK25MiTrAEccL/BaZ4DBBT2plPNhvjH # BA1yRg2liBKQL6ctN4Ei4DHmvEw5IQrbWBVnEpl6GZtTDf5GeeE/22awJci1ooJM # XqkH+ypqmwaM9aaXSI6j2Ai5NtE6AFmnQjHmvd7cOTgyU/jr6MslNw4acO+ZJ+uO # g2Gs4AA4c1gPWIUPVR6eqYCXAvNLCgcSBWXsZKUAsfUr/tf5TQVNDK5tJL/XiPLt # jFkYYB8ZdUaab4IOrL9fHFQ16WsEGQftT++Qm8L6u+zmP578dgfOXCgs7E7ffNsh # Zvk= # SIG # End signature block |