targetgroupmgmt.ps1
# Setup APIs function New-ICTargetGroup { [cmdletbinding()] param( [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Name, [parameter(Mandatory=$false)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [String]$ControllerGroupId, [parameter(HelpMessage="Use first available ControllerGroupId if not provided.")] [Switch]$Force ) $Endpoint = "targets" $body = @{ name = $Name } if ($ControllerGroupId) { $body['controllerGroupId'] = $ControllerGroupId } else { $cg = Get-ICControllerGroup if ($cg.count -gt 1 -AND $Force) { $body['controllerGroupId'] = ($cg | Sort-Object createdOn -Desc)[0].id } elseif ($cg.count -gt 1) { Write-Error "More than one Controller Group. Recommend specifying a ControllerGroupId. Available Options: `n$($cg | Format-Table -auto | Out-String)" return } else { $body['controllerGroupId'] = $cg.id } } $tg = Get-ICTargetGroup -where @{ name = $Name } if ($tg) { Write-Error "There is already a Target Group named $Name" } else { Write-Verbose "Creating new target group: $Name" Invoke-ICAPI -Endpoint $Endpoint -body $body -method POST } } function Get-ICTargetGroup { [cmdletbinding()] param( [parameter(ValueFromPipeline=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('TargetGroupId','targetId')] [String]$Id, [Switch]$IncludeArchive, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { if ($IncludeArchive) { $Endpoint = "TargetsArchive" } else { $Endpoint = "targets" } if ($Id) { $Endpoint += "/$Id" } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } function Remove-ICTargetGroup { [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('TargetGroupId','targetId')] [String]$Id, [Switch]$IncludeArchive ) PROCESS { $obj = Get-ICTargetGroup -id $Id if (-NOT $obj) { Write-Error "No target group with id '$Id' exists." return } if ($IncludeArchive) { $Endpoint = "TargetsArchive/$Id" } else { $Endpoint = "targets/$Id" } Write-Warning "Careful. This will remove access to all scan data within this target group and is only reversible for the next 7 days" if ($PSCmdlet.ShouldProcess($tg.name, "Will remove target group: $($obj.name) [$Id]")) { Write-Warning "Removing target group: $($obj.name) [$Id]." Invoke-ICAPI -Endpoint $Endpoint -method 'DELETE' } } } function New-ICControllerGroup { [cmdletbinding()] param( [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Name ) $Endpoint = "controllergroups" $body = @{ name = $Name; } $cg = Get-ICControllerGroup -where @{ name = $Name; deleted = $False } if ($cg) { Write-Error "There is already a Controller Group named $Name" } else { Write-Verbose "Creating new Controller Group: $Name [$HuntServerAddress/api/$Endpoint]" Invoke-ICAPI -Endpoint $Endpoint -body $body -method POST } } function Get-ICControllerGroup { [cmdletbinding()] param( [parameter(ValueFromPipeline=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('controllerGroupId')] [String]$Id, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $Endpoint = "controllergroups" if ($Id) { $Endpoint += "/$id" } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } function Remove-ICControllerGroup { [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('ControllerGroupId')] [String]$Id ) PROCESS { $Endpoint = "controllergroups/$Id" $obj = Get-ICControllerGroup -id $Id if (-NOT $obj) { Write-Error "No Controller Group with id '$Id' exists." return } if ($PSCmdlet.ShouldProcess($obj.name, "Will remove target group: $($obj.name) [$Id]")) { Write-Warning "Removing Controller Group $Id." Invoke-ICAPI -Endpoint $Endpoint -method 'DELETE' } } } function New-ICCredential { [cmdletbinding()] Param( [parameter(Mandatory=$True)] [String]$Name, [parameter(Mandatory=$True)] [PSCredential]$Cred, [parameter()] [ValidateSet("windowsLocal","windowsDomain","aws","ssh","login","linuxSudo")] [String]$AccountType="login" ) $Endpoint = "credentials" $body = @{ name = $Name username = $Cred.Username password = $Cred.GetNetworkCredential().Password byok = $False login = $AccountType } $c = Get-ICCredential -where @{ name = $Name; deleted = $False } if ($c) { Write-Error "There is already a credential object named $Name" } else { Write-Verbose "Adding new Credential $Name [$($Cred.Username)] to the Credential Manager" Invoke-ICAPI -Endpoint $Endpoint -body $body -method POST } } function Get-ICCredential { [cmdletbinding()] param( [parameter(ValueFromPipeline=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('credentialId')] [String]$id, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $Endpoint = "credentials" if ($id) { $Endpoint += "/$id" } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } function Remove-ICCredential { [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [alias('credentialId')] [String]$Id ) PROCESS { $Endpoint = "credentials/$Id" $obj = Get-ICCredential -id $Id if (-NOT $obj) { Write-Error "No target group with id '$Id' exists." return } if ($PSCmdlet.ShouldProcess($obj.name, "Will remove Credential Object: $($obj.name) [$Id]")) { Write-Warning "Removing Credential $($obj.name) [$Id]." Invoke-ICAPI -Endpoint $Endpoint -method 'DELETE' } } } function Get-ICAddress { [cmdletbinding()] param( [parameter()] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('addressId')] [String]$Id, [parameter(ValueFromPipeLine=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('targetId')] [String]$TargetGroupId, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $Endpoint = "Addresses" if ($Id) { Write-Verbose "Getting Address with id: $Id" $Endpoint += "/$Id" } elseif ($TargetGroupId) { Write-Verbose "Getting all Addresses from TargetGroup: $TargetGroupId" $where += @{ targetId = $TargetGroupId } } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } function Remove-ICAddress { [cmdletbinding(SupportsShouldProcess=$true)] Param( [parameter( ValueFromPipelineByPropertyName, ValueFromPipeLine)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('AddressId')] [String]$id, [parameter(ValueFromPipelineByPropertyName=$true)] [alias('targetId')] [String]$TargetGroupId ) PROCESS { $Endpoint = "Addresses" if ($Id) { $obj = Get-ICAddress -id $Id if (-NOT $obj) { Write-Error "No Address with id '$Id' exists." return } if ($PSCmdlet.ShouldProcess($obj.hostname, "Will remove Address: $($obj.hostname) [$Id]")) { Write-Warning "Removing Address $($obj.hostname) [$Id]." $Endpoint = "Addresses/$id" } } elseif ($TargetGroupId) { $obj = Get-ICTargetGroup -id $TargetGroupId if (-NOT $obj) { Write-Error "No Target Group with id '$TargetGroupId' exists." return } if ($PSCmdlet.ShouldProcess($obj.name , "Clearing ALL Addresses from Target Group: $($obj.name) [$TargetGroupId]")) { Write-Warning "Clearing all Addresses from TargetGroup: $($obj.name) [$TargetGroupId]" $body['where'] = @{ targetId = $TargetGroupId } } } else { Write-Error "Provide either an addressId or a targetGroupId." return } Invoke-ICAPI -Endpoint $Endpoint -body $body -method DELETE } } function Get-ICAgent { [cmdletbinding()] param( [parameter(ValueFromPipeline=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('agentId')] [String]$Id, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { if ($Id) { $CountOnly = $False $Endpoint = "Agents/$Id" } else { $Endpoint = "Agents" } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$NoLimit -CountOnly:$CountOnly } } function Remove-ICAgent { [cmdletbinding(SupportsShouldProcess=$true)] Param( [parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('AgentId')] [String]$Id ) PROCESS { $Endpoint = "Agents/$Id" $obj = Get-ICAgent -id $Id if (-NOT $obj) { Write-Error "No Agent exists with id: $Id" return } if ($PSCmdlet.ShouldProcess($obj.hostname, "Will uninstall agent: $($obj.hostname) [$Id]")) { Write-Verbose "Uninstalling Agent $($obj.hostname) [$Id]." Invoke-ICAPI -Endpoint "$Endpoint/uninstall" -method POST | Out-Null Write-Verbose "Agent on $($obj.hostname) [$Id] uninstalled and deleted." return $true } } } function New-ICQuery { [cmdletbinding()] Param( [parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [alias('QueryName')] [String]$Name, [parameter(Mandatory=$True)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('targetId')] [String]$TargetGroupId, [parameter(Mandatory=$True)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [String]$credentialId, [parameter()] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [String]$sshCredentialId, [parameter(Mandatory=$True)] [ValidateNotNullorEmpty()] [String]$Query ) $Credential = Get-ICCredential -Id $CredentialId if (-NOT $Credential) { Throw "Credential with CredentialId $CredentialId does not exist." } $TargetGroup = Get-ICTargetGroup -Id $TargetGroupId if (-NOT $TargetGroup) { Throw "Credential with TargetGroup $TargetGroupId does not exist." } Write-Verbose "Creating new Query $Name ($query) in TargetGroup $($TargetGroup.name) using credential $($Credential.name) [$($Credential.username)]" $Endpoint = "queries" $body = @{ name = $Name value = $query targetId = $TargetGroupId credentialId = $CredentialId } if ($sshCredentialId) { $body['sshCredential'] = $sshCredentialId } Invoke-ICAPI -Endpoint $Endpoint -body $body -method POST } function Get-ICQuery { [cmdletbinding()] param( [parameter(ValueFromPipeline=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('queryId')] [String]$Id, [parameter(ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('targetId')] [String]$TargetGroupId, [parameter(HelpMessage="This will convert a hashtable into a JSON-encoded Loopback Where-filter: https://loopback.io/doc/en/lb2/Where-filter ")] [HashTable]$where=@{}, [Switch]$NoLimit, [Switch]$CountOnly ) PROCESS { $Endpoint = "queries" if ($Id) { Write-Verbose "Getting Query: $Id" $Endpoint += "/$Id" } elseif ($TargetGroupId) { Write-Verbose "Getting Queries for Target Group Id: $TargetGroupId" $where += @{ targetId = $TargetGroupId } } Get-ICAPI -Endpoint $Endpoint -where $where -NoLimit:$true -CountOnly:$CountOnly } } function Remove-ICQuery { [cmdletbinding(SupportsShouldProcess=$true)] param( [parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if ($_ -match $GUID_REGEX) { $true } else { throw "Incorrect input: $_. Should be a guid."} })] [alias('queryId')] [String]$Id ) PROCESS { $Endpoint = "queries/$Id" if ($PSCmdlet.ShouldProcess($Id, "Will remove this query")) { Write-Warning "Removing query $Id" Invoke-ICAPI -Endpoint $Endpoint -method 'DELETE' } } } # SIG # Begin signature block # MIINOAYJKoZIhvcNAQcCoIINKTCCDSUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUumNKxZlpIopPjofB+Cj3tedB # ct2gggp2MIIFHzCCBAegAwIBAgIQA7ShIT20JORyIag/jWOSyzANBgkqhkiG9w0B # AQsFADB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBTSEEyIEhp # Z2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTAeFw0xODA5MTIwMDAwMDBaFw0y # MDExMTgxMjAwMDBaMF4xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVUZXhhczEPMA0G # A1UEBxMGQXVzdGluMRYwFAYDVQQKEw1JbmZvY3l0ZSwgSW5jMRYwFAYDVQQDEw1J # bmZvY3l0ZSwgSW5jMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzcR # GuszlupWLdmtti4glKsr6SS2sp370yioc2XyIwPzU/etsBQa41x6VO7HXjtSXSry # p3SYaoLPQmBiAzKjDP6dzu0l7cQFbwPMky3SGqrC3Wr+Kw/qoMgn3wKBxzPJ53Gj # s1oxNwyz2N7FwN977vErW9C/FgM/XuE7Zde/HGl3oxTJNtY++BG2Ri3rwi5hNbzV # 5+avrJFW1DzHVBXYxbrE9vNy4V6s7dlZT2xZoJ3AtHoBCUMgHRKii3wHgFRaxiuz # 6XzlvHzmnh02KUfoV6cX++bP4bRtsJjmvrfJV+Mhlh/MhUidhhQQx0spLIfxv+vZ # OACP5jLm0g2fj4G4VQIDAQABo4IBvzCCAbswHwYDVR0jBBgwFoAUZ50PIAkMzIo6 # 5YJGcmL88cyQ5UAwHQYDVR0OBBYEFBqi6MjBKip4kQYxVCjC7yOrUHWFMA4GA1Ud # DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzBtBgNVHR8EZjBkMDCgLqAs # hipodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1jcy1nMS5jcmwwMKAu # oCyGKmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLWNzLWcxLmNybDBM # BgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3 # dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBiAYIKwYBBQUHAQEEfDB6MCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wUgYIKwYBBQUHMAKG # Rmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNz # dXJhbmNlQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0B # AQsFAAOCAQEABnQP0mJYXNzfz4pMCc4FbQ9qe8NjloGuIlUgXaxlFAoMKZWMueXq # mciPWULaE+Wd5ChTuNsrWKG7bWYYWmmo7C1RWhdZhQT/C+k3lFcsSr6gdXAXiOmv # 3xv3d3oqfNe19G6jt6akQ6LjEauRw4xKinoK/S61Pw9c1KtEAGT8djgX74h433fy # FPiQd//ePnihKN+GXRCeLvSaDGuVrhHuI6UUhe3MK2/Nb8MzFddwkOOdpky1HBn4 # 8oFEAOzbrTVTTv4BWLNRvAiY8UO3D2Kt322UuAdXIKNxWB94UaFt2jg2QsRkTHGQ # MmbQ8OgMIWWNcE9RcVKuobYbzUAGPoMimTCCBU8wggQ3oAMCAQICEAt+EJA8OEkP # +i9nmoehp7kwDQYJKoZIhvcNAQELBQAwbDELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UE # AxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTAeFw0xMzEwMjIx # MjAwMDBaFw0yODEwMjIxMjAwMDBaMHYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE # aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xNTAzBgNVBAMT # LERpZ2lDZXJ0IFNIQTIgSGlnaCBBc3N1cmFuY2UgQ29kZSBTaWduaW5nIENBMIIB # IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtEpefQcPQd7E9XYWNr1x/88/ # T3NLnNEN/krLV1hehRbdAhVUmfCPPC9NAngQaMjYNUs/wfdnzpgcrjO5LR2kClST # xIWi3zWx9fE8p7M0+11IyUbJYkS8SJnrKElTwz2PwA7eNZjpYlHfPWtAYe4EQdrP # p1xWltH5TLdEhIeYaeWCuRPmVb/IknCSCjFvf4syq89rWp9ixD7uvu1ZpFN/C/FS # iIp7Cmcky5DN7NJNNEyw4bWfnMb2byzN5spTdAGfZzXeOEktzu05RIIZeU4asrX7 # u3jwSWanz/pclnWSixpy2f9QklPMPsJDMgkahhNpPPuBMjMyZHVzKCYdCDA7BwID # AQABo4IB4TCCAd0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYw # EwYDVR0lBAwwCgYIKwYBBQUHAwMwfwYIKwYBBQUHAQEEczBxMCQGCCsGAQUFBzAB # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSQYIKwYBBQUHMAKGPWh0dHA6Ly9j # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RD # QS5jcnQwgY8GA1UdHwSBhzCBhDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9v # dENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYc # aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4E # FgQUZ50PIAkMzIo65YJGcmL88cyQ5UAwHwYDVR0jBBgwFoAUsT7DaQP4v0cB1Jgm # GggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBAGoO/34TfAalS8AujPlTZAniuliR # MFDszJ/h06gvSEY2GCnQeChfmFZADx66vbE7h1zcW9ggDe0aFk3VESQhS/EnaZAT # 6xGhAdr9tU55WXW9OCpqw/aOQSuKoovXLFFR2ZygyONOumyoR9JO0WgfjAJXO7Mp # ao5qICq58gBiZLrI6QD5zKTUupo12K8sZWwWfFgh3kow0PrrJF0GyZ0Wt61KRdMl # 4gzwQKpcTax+zQaCuXZGaQjYMraC/uOpWDRDG45nZ5c/aDEWNjiVPof3x8OvnXp3 # Gdnek7X9biv8lPk9t0wSNSwwvuiNngVwmkgT9IzW5x6sOOeo860Mt3rsZ+0xggIs # MIICKAIBATCBijB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBT # SEEyIEhpZ2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQQIQA7ShIT20JORyIag/ # jWOSyzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC # NwIBFTAjBgkqhkiG9w0BCQQxFgQU9fA818tIBdyLHe5zljweGcGdZl4wDQYJKoZI # hvcNAQEBBQAEggEAHPofJfzls6QCqIWFRUJDw6cW57RiJX5mdW3/g/iOaJvuQlbH # BXTdVkGJA4/xcknJ01oPchxIHekoNqXbBuuaHXAfB8XhPqduHs2q7jka84Yiwtx1 # 4RHdgHx95SKlOQAL07Q0u8KnwF8EOItPdTls6tJ7qDNLD07ioQcPXONtukp5QRmI # zBSsXssazcGwIQeB1OHxCLZzUJ9DyiVcR02R//Pl7zelumbIKCfBDHxWSU7C365M # YONOR48w/tY+wC+nq2OLQx8Urpk4roT36YFI0T8sbbTMmOYf/Sk6Hy7NmMasVaqa # ueou8zuO6RQU1G7rpat6KEN+bRfIZenxFy0NBw== # SIG # End signature block |