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/uninstall" $obj = Get-ICAgent -id $Id if (-NOT $obj) { Write-Error "No Agent exists with id: $Id" return } $body = @{ where = @{ id = $Id } } if ($PSCmdlet.ShouldProcess($obj.hostname, "Will uninstall agent: $($obj.hostname) [$Id]")) { Write-Verbose "Uninstalling Agent $($obj.hostname) [$Id]." Invoke-ICAPI -Endpoint $Endpoint -body $body -method POST Write-Verbose "Uninstall pending for Agent on $($obj.hostname) [$Id]." 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 # MIINFwYJKoZIhvcNAQcCoIINCDCCDQQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUr7Iaqc5wMaCIq3Z8BAAu5SED # BS2gggpZMIIFITCCBAmgAwIBAgIQD1SHruUyzkN01AFx5d7oATANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTExNzAwMDAwMFoXDTIyMTEy # OTIzNTk1OVowXjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQH # EwZBdXN0aW4xFjAUBgNVBAoTDUluZm9jeXRlLCBJbmMxFjAUBgNVBAMTDUluZm9j # eXRlLCBJbmMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNUhaEiZbu # H7Q6oqA0uq0klkstXkdJU3eJukMrrLpxKdtFqtJwFXcSYp5G/WFlwDRJ8v8fisfp # SiPS1WajFUHe3EWLh2oXjf44eQYVWQ8SqAn2J8dDLNJ5bWY0w7MD2GrSiTwN0Vi9 # X9pJKJDdm7mJo7bSlZ9p7XvNoraSAx/hkODalPSMvCIVAEOZutlzeWyJ4p0DbTDA # kjQPF4EZ7JqxYXFeItoi0uYZQNEHbBxr+5SG45ziC8vuwyljIbo+mKD/PwT48OQl # 9cdnI651Hz+r5kL3t48WvxYrAUJ7g8EJyw2uYnVnSroIC3TmUQHeXS6FuqeObuX7 # MqapBKRcTHvxAgMBAAGjggHFMIIBwTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg # +S32ZXUOWDAdBgNVHQ4EFgQUxKDwshqav/aGaGVOFv67CuwSjcYwDgYDVR0PAQH/ # BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0 # dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWg # M6Axhi9odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx # LmNybDBMBgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRw # czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEE # eDB2MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYB # BQUHMAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJB # c3N1cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3 # DQEBCwUAA4IBAQByJW5tIcmouIY7tdngPLdEOM4FYqLGf9IjKPMS0s+NeTaP/0hp # dmNeGFEvMozfgDA/gPFCUaRVJwy4rKsGnCznCE1YDA6UFDGZq3VLUbzC6GDP4aY8 # EbfDMbF54TVuOKRue9a6KnVE67gOj+g862qAR6fm/GdeO/KrdvCT1A7xbyg02cCq # +QgdkYoxI3bsiUwgZ33I2rn2T2zSp8C+RX2bZ8rgtXHxgYLCJdayqMptRsPbxOlQ # Z7dRhkQXg5D/PyUnpWASF+sLQQ0IMvx8ZKy/P01IhKU0pTJ8OFSYKwPLQnYm1Zp0 # JT/IXZ/tzmtY/StdhaCs3LlOkuHxl2iERxdtMIIFMDCCBBigAwIBAgIQBAkYG1/V # u2Z1U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UE # ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD # VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAw # WhcNMjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl # cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp # Q2VydCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/ # 5aid2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH # 03sjlOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxK # hwjfDPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr # /mzLfnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi # 6CxR93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCC # AckwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAww # CgYIKwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6 # MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy # ZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E # aWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1s # AAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMw # CgYIYIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1Ud # IwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+ # 7A1aJLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbR # knUPUbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7 # uq+1UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7 # qPjFEmifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPa # s7CM1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR # 6mhsRDKyZqHnGKSaZFHvMYICKDCCAiQCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx # MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBD # QQIQD1SHruUyzkN01AFx5d7oATAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEK # MAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3 # AgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUb89UFwbd3PVf00Zr # n8/ib1Dvxr8wDQYJKoZIhvcNAQEBBQAEggEAdkP+OHCyUM153Cm1/1L7pkMZKueA # 4XKnAHlF/wlAZYpm1gup2Lb0tr8ZdLNh7Jz7NNqGIwn5rd4QEajEuuIhSFTP4BK5 # aRV7jtVShjrjLnM5JXDRguhXpO+Y0oZ8olEtaFqEEZLlvIlYruw72zFo1JGn7BsL # oQX24MtpNWSyVrkVJgAhpkc1vCvhpDdwtqi1IsmkbKew6sS8awprpnbMnaGGZFd8 # zroz1a75Se7c5GzwSmWkmxgYAMaplVSD2XIHut9OEoY68AXrIBsStiasiQkqj+5L # RNn7pGJAzbyyA+aG3/B1aUOW7hiEObPTAD31/uOsdqtO1hF7yZ27vvh0vw== # SIG # End signature block |