CyberInt.IoC.psm1

function Invoke-CyberintApiRequest {
  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [string]$Endpoint,

    [Parameter(Mandatory = $true)]
    [string]$Method,

    [Parameter(Mandatory = $true)]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $false)]
    [hashtable]$QueryParams = @{},

    [Parameter(Mandatory = $true)]
    [string]$BaseUrl
  )

  begin {
    $uri = "{0}{1}" -f $BaseUrl, $Endpoint
    $accessToken = $Credential.GetNetworkCredential().Password
  }

  process {
    if ($QueryParams.Count -gt 0) {
      $queryString = [System.Web.HttpUtility]::ParseQueryString('')
      foreach ($param in $QueryParams.GetEnumerator()) {
        $queryString[$param.Key] = $param.Value
      }
      $uri = "{0}?{1}" -f $uri, $queryString.ToString()
    }

    $headers = @{
      "Cookie" = "access_token={0}" -f $accessToken
    }

    try {
      $response = Invoke-RestMethod -Uri $uri -Method $Method -Headers $headers -ContentType "application/json" -ErrorAction Stop
      Write-Output -InputObject $response
    }
    catch {
      $statusCode = $_.Exception.Response.StatusCode.value__
      $errorMessage = $_.Exception.Message

      switch ($statusCode) {
        401 { Write-Error ("Authentication failed: Invalid credentials") -ErrorAction Stop }
        403 { Write-Error ("Access denied: Insufficient permissions") -ErrorAction Stop }
        422 { Write-Error ("Invalid input: {0}" -f $errorMessage) -ErrorAction Stop }
        429 { Write-Error ("Rate limit exceeded") -ErrorAction Stop }
        404 { Write-Error ("Resource not found") -ErrorAction Stop }
        default { Write-Error ("Error {0}: {1}" -f $statusCode, $errorMessage) -ErrorAction Stop }
      }
    }
  }
}

function Get-CyberintDomain {
  <#
    .SYNOPSIS
    Retrieves IOC information for a domain.
 
    .PARAMETER Value
    The domain name
 
    .PARAMETER Credential
    PSCredential object containing the API access token
 
    .PARAMETER BaseUrl
    The base URL of the customer's API instance
    #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^(?:(?:(?:[[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?)\.))*(?:[a-z0-9][a-z0-9\-]*[a-z0-9])$")]
    [string]$Value,

    [Parameter(Mandatory = $true)]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $true)]
    [string]$BaseUrl
  )

  process {
    $queryParams = @{ value = $Value }
    Invoke-CyberintApiRequest -Endpoint "/api/v1/domain" -Method "GET" -Credential $Credential -QueryParams $queryParams -BaseUrl $BaseUrl
  }
}

function Get-CyberintDailyFeed {
  <#
    .SYNOPSIS
    Downloads daily IOC feed, either for a specific date or by type and activity.
 
    .PARAMETER Date
    The date in YYYY-MM-DD format
 
    .PARAMETER Limit
    Number of items to retrieve (BasicFeed only)
 
    .PARAMETER Offset
    Number of items to skip (BasicFeed only)
 
    .PARAMETER Format
    The desired output format (jsonl, csv, json, txt)
 
    .PARAMETER DetectedActivity
    The detected activity type (TypedFeed only)
 
    .PARAMETER IocType
    The IOC type (file/sha256, ipv4, domain, url) (TypedFeed only)
 
    .PARAMETER Credential
    PSCredential object containing the API access token
 
    .PARAMETER BaseUrl
    The base URL of the customer's API instance
    #>

  [CmdletBinding(DefaultParameterSetName = 'BasicFeed')]
  param (
    [Parameter(Mandatory = $true, ParameterSetName = 'BasicFeed')]
    [Parameter(Mandatory = $true, ParameterSetName = 'TypedFeed')]
    [ValidatePattern("^\d{4}-\d{2}-\d{2}$")]
    [string]$Date,

    [Parameter(Mandatory = $false, ParameterSetName = 'BasicFeed')]
    [int]$Limit,

    [Parameter(Mandatory = $false, ParameterSetName = 'BasicFeed')]
    [int]$Offset,

    [Parameter(Mandatory = $false, ParameterSetName = 'BasicFeed')]
    [Parameter(Mandatory = $false, ParameterSetName = 'TypedFeed')]
    [ValidateSet("jsonl", "csv", "json", "txt")]
    [string]$Format = "jsonl",

    [Parameter(Mandatory = $true, ParameterSetName = 'TypedFeed')]
    [ValidateSet("malware_payload", "cnc_server", "infected_machine", "phishing_website", "payload_delivery", "cc_skimming",
      "botnet", "anonymization", "unclassified", "n/a", "adware", "volatile_website", "benign", "compromised_website",
      "phishing", "infecting_website", "infecting_url", "web_hosting", "file_hosting", "parked", "spam", "cryptominer",
      "riskware", "unknown", "volatile", "compromised_server", "infection_source", "scanner", "anonymiser",
      "compromised_host")]
    [string]$DetectedActivity,

    [Parameter(Mandatory = $true, ParameterSetName = 'TypedFeed')]
    [ValidateSet("file/sha256", "ipv4", "domain", "url")]
    [string]$IocType,

    [Parameter(Mandatory = $true, ParameterSetName = 'BasicFeed')]
    [Parameter(Mandatory = $true, ParameterSetName = 'TypedFeed')]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $true, ParameterSetName = 'BasicFeed')]
    [Parameter(Mandatory = $true, ParameterSetName = 'TypedFeed')]
    [string]$BaseUrl
  )

  process {
    $queryParams = @{}
    $endpoint = "/api/v1/feed/daily"

    if ($PSCmdlet.ParameterSetName -eq 'BasicFeed') {
      $endpoint = "/api/v1/feed/daily/{0}" -f $Date
      if ($PSBoundParameters.ContainsKey('Limit')) { $queryParams["limit"] = $Limit }
      if ($PSBoundParameters.ContainsKey('Offset')) { $queryParams["offset"] = $Offset }
      if ($PSBoundParameters.ContainsKey('Format')) { $queryParams["format"] = $Format }
    }
    else {
      $queryParams = @{
        detected_activity = $DetectedActivity
        ioc_type          = $IocType
        date              = $Date
        format            = $Format
      }
    }

    Invoke-CyberintApiRequest -Endpoint $endpoint -Method "GET" -Credential $Credential -QueryParams $queryParams -BaseUrl $BaseUrl
  }
}

function Get-CyberintFileSha256 {
  <#
    .SYNOPSIS
    Retrieves IOC information for a file SHA256 hash.
 
    .PARAMETER Value
    The SHA256 hash value (64 hexadecimal characters)
 
    .PARAMETER Credential
    PSCredential object containing the API access token
 
    .PARAMETER BaseUrl
    The base URL of the customer's API instance
    #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-f0-9]{64}$")]
    [string]$Value,

    [Parameter(Mandatory = $true)]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $true)]
    [string]$BaseUrl
  )

  process {
    $queryParams = @{ value = $Value }
    Invoke-CyberintApiRequest -Endpoint "/api/v1/file/sha256" -Method "GET" -Credential $Credential -QueryParams $queryParams -BaseUrl $BaseUrl
  }
}

function Get-CyberintIPv4 {
  <#
    .SYNOPSIS
    Retrieves IOC information for an IPv4 address.
 
    .PARAMETER Value
    The IPv4 address
 
    .PARAMETER Credential
    PSCredential object containing the API access token
 
    .PARAMETER BaseUrl
    The base URL of the customer's API instance
    #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [ValidateScript({ $_ -match [System.Net.IPAddress]::IPv4Mask })]
    [string]$Value,

    [Parameter(Mandatory = $true)]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $true)]
    [string]$BaseUrl
  )

  process {
    $queryParams = @{ value = $Value }
    Invoke-CyberintApiRequest -Endpoint "/api/v1/ipv4" -Method "GET" -Credential $Credential -QueryParams $queryParams -BaseUrl $BaseUrl
  }
}

function Get-CyberintUrl {
  <#
    .SYNOPSIS
    Retrieves IOC information for a URL.
 
    .PARAMETER Value
    The URL (max 2083 characters)
 
    .PARAMETER Credential
    PSCredential object containing the API access token
 
    .PARAMETER BaseUrl
    The base URL of the customer's API instance
    #>

  [CmdletBinding()]
  param (
    [Parameter(Mandatory = $true)]
    [ValidateLength(1, 2083)]
    [uri]$Value,

    [Parameter(Mandatory = $true)]
    [PSCredential]$Credential,

    [Parameter(Mandatory = $true)]
    [string]$BaseUrl
  )

  process {
    $queryParams = @{ value = $Value.ToString() }
    Invoke-CyberintApiRequest -Endpoint "/api/v1/url" -Method "GET" -Credential $Credential -QueryParams $queryParams -BaseUrl $BaseUrl
  }
}

Export-ModuleMember -Function Get-CyberintDomain, Get-CyberintDailyFeed, Get-CyberintFileSha256, Get-CyberintIPv4, Get-CyberintUrl

# SIG # Begin signature block
# MIIt4gYJKoZIhvcNAQcCoIIt0zCCLc8CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDmqxGT7SyN4nQ3
# zGFnsaeJcxioB3gIu6fxghKhHGiVPqCCEyswggWQMIIDeKADAgECAhAFmxtXno4h
# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
# eE4wggbfMIIEx6ADAgECAhADOvN90luA0nrA93Kao14iMA0GCSqGSIb3DQEBCwUA
# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
# ODQgMjAyMSBDQTEwHhcNMjQxMjE5MDAwMDAwWhcNMjYwMTE2MjM1OTU5WjBnMQsw
# CQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExFTATBgNVBAcTDE5vdHRpbmcg
# SGlsbDEWMBQGA1UEChMNSVBTZWMgUHR5IEx0ZDEWMBQGA1UEAxMNSVBTZWMgUHR5
# IEx0ZDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKAKgpRe3of6uvFi
# CACixkD18+fCx2CROSBlMrWeSwogIGRx2Gm/BEZhUzGLPVAXN33pPlYo95K2aben
# DHHuN6JV/fEjEphS9c3bm+QgP1q96uceh+ytVY0oq3uONcDdYIOR/kdCkH07lPo3
# jPEEkFfyKsNFH+DpaFwLqq8fmzj9euT5JSGRlZi5mC0qquZ0hEVNkFQ3vhV6vW4a
# AQ4YlkgYs4Fl7DHZKSnwwHTYCSjmZzJVaX3GcR2yZv5vrkEWGfP0IcXZAPwnHDjd
# jSWfTSmfMLu0Yh6rWmtm1Hw/2/3CWmkMGv0yYFxevuso3FkuuesnqS/sNxJP29BR
# DauxouAVbp8ipOg1oaQvpkWsFMzb36DCdKHWWSmIbCp5niUwMiLsg/8mYYRf+T1I
# JsAPZYXY5taIQssBBmlUJgiIxACEw52mc6fjy+35wK69X12OTnYRfZQ2ORa/JUIX
# SZ2VkQZ4qDLzJyZWWUwXipPyLHhXMJw7oxnNU4ocFwcxL9/SQwIDAQABo4ICAzCC
# Af8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFBT8
# Z08ugGGhp3FyFX/0iw9X9KENMD4GA1UdIAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYB
# BQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMC
# B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0
# cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25p
# bmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
# QTM4NDIwMjFDQTEuY3JsMIGUBggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYY
# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2Fj
# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JT
# QTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUA
# A4ICAQC6aprHmEJvSXJ+yM3xzoN1W8to3bZBh2MtR6+UIuXC/q9lxCrW6ZlJTmRc
# wodjaP6aX4r4oaWwbe7DuYkCSDylP995O+WA46Tu3KqmGBrPQQWzlfLx0Uv3dMvN
# Da2I314DtOwK4Ynrl2MBgfJdxns8YK1fdk2vfVm5dMG63GSzh+Prgwt20K4AyI4C
# GCljQy61sud7pVcNlJs0jjDq7yRT4IOu9jFazx7nqrhBbyllcx/qog5w+u2W58tx
# Se/SVHbTcizoXxyluCCPfspQ+EYTVCC5BTSHpF7iRxHmthmUEamUI4/vh7cwmQG6
# Rtq0wNNYnLq29JpcvrxV4GDmtZGb2Iok0+/YZUoTuTp5zk3RZ034FAszBbTQ+vbn
# 87xa+Pckkx5PZYJsx8KCSZ1TJtPZSegy7pMMWYNfcHd5s9NNt/aOFdCqjuVSKJGH
# zaIY09oS0ClUUCHNQaVQJAF0daLWwo3WmOywaziXTmYR+5rSfNl9aGzzrW+ardL8
# IIzLURVE/VHJ+NHCdB+kiuWaE0ivHKjBxIvpKUNeoQTeSTzZ/aRbhAx1hDANa4MB
# Z1jdB4/jWsGbVE8aY4WSdmw3BOEGhm2mc3S6QVdMF8Be98V+JEqJXmg1nD9ySok4
# 55d3duhIe3KsYB/lJx9uLzn+e0bwXHDu63AAMi6pkLB1x3/hSDGCGg0wghoJAgEB
# MH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYD
# VQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNI
# QTM4NCAyMDIxIENBMQIQAzrzfdJbgNJ6wPdymqNeIjANBglghkgBZQMEAgEFAKCB
# hDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEE
# AYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJ
# BDEiBCC7P0R03KCvtc7/8/fSkEwqC2tHdHiyDaLfj075OnwBfTANBgkqhkiG9w0B
# AQEFAASCAYBmJITfOGDTvV5oaXqfhRuCvqhufRIdOedkdqXFSmLHLTmD9lO9hVvc
# vH2GYhTdM0TV3iLs73Ty0D6xiWOfbYeNSYsf2KQpb+7itPzQTQi58J0u8QsbLl1v
# TMwo5t5osbT0toMMlz7Vt0ck0+RIcjDp8+xgsA2wSkZPwhnWUXl9xfEfd+UCrC8Y
# ymywznc/j2/M2GTeaffUynmsFl5zaPHcFw3WagzPfpjptg0CYw0a09yPF31iMyyd
# 9OOeJdIorPnB4uKiSzNqrfEfAFjhNAlCqR3s9QZA5FWMCb8LFBso3XJr7itjof0S
# 5E2rUpsysLkUXP0nZ77jkB1M8qmPMo652eO2CEobEqxV8GhFMJAmCfLQhnEwWd1c
# MB/mOocYIiSdONy8jUj4LLpdmCCYdit8R5f1GBqK/UQCFKKOg4mNP+2FtZLwHOyz
# 3qyrx4/cJbFmGV3wUsXLCqp8kmP1Mglg/Wpv0a4sSY3FhL5BAaI8ArT6GXllAVHY
# kHyDwG+DFEShghdaMIIXVgYKKwYBBAGCNwMDATGCF0YwghdCBgkqhkiG9w0BBwKg
# ghczMIIXLwIBAzEPMA0GCWCGSAFlAwQCAgUAMIGHBgsqhkiG9w0BCRABBKB4BHYw
# dAIBAQYJYIZIAYb9bAcBMEEwDQYJYIZIAWUDBAICBQAEMKZbdemcFNSIrirDFvkk
# V4f9C0LHUDcgatbnGYMxYJL9ujLCHsjv+tF1k2SxaiQGcgIQSkd46pGTyFgDBLiD
# g1DQdRgPMjAyNTAzMjcwNTEyNDRaoIITAzCCBrwwggSkoAMCAQICEAuuZrxaun+V
# h8b56QTjMwQwDQYJKoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoT
# DkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJT
# QTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTAeFw0yNDA5MjYwMDAwMDBaFw0z
# NTExMjUyMzU5NTlaMEIxCzAJBgNVBAYTAlVTMREwDwYDVQQKEwhEaWdpQ2VydDEg
# MB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjQwggIiMA0GCSqGSIb3DQEB
# AQUAA4ICDwAwggIKAoICAQC+anOf9pUhq5Ywultt5lmjtej9kR8YxIg7apnjpcH9
# CjAgQxK+CMR0Rne/i+utMeV5bUlYYSuuM4vQngvQepVHVzNLO9RDnEXvPghCaft0
# djvKKO+hDu6ObS7rJcXa/UKvNminKQPTv/1+kBPgHGlP28mgmoCw/xi6FG9+Un1h
# 4eN6zh926SxMe6We2r1Z6VFZj75MU/HNmtsgtFjKfITLutLWUdAoWle+jYZ49+wx
# GE1/UXjWfISDmHuI5e/6+NfQrxGFSKx+rDdNMsePW6FLrphfYtk/FLihp/feun0e
# V+pIF496OVh4R1TvjQYpAztJpVIfdNsEvxHofBf1BWkadc+Up0Th8EifkEEWdX4r
# A/FE1Q0rqViTbLVZIqi6viEk3RIySho1XyHLIAOJfXG5PEppc3XYeBH7xa6VTZ3r
# OHNeiYnY+V4j1XbJ+Z9dI8ZhqcaDHOoj5KGg4YuiYx3eYm33aebsyF6eD9MF5IDb
# PgjvwmnAalNEeJPvIeoGJXaeBQjIK13SlnzODdLtuThALhGtyconcVuPI8AaiCai
# JnfdzUcb3dWnqUnjXkRFwLtsVAxFvGqsxUA2Jq/WTjbnNjIUzIs3ITVC6VBKAOlb
# 2u29Vwgfta8b2ypi6n2PzP0nVepsFk8nlcuWfyZLzBaZ0MucEdeBiXL+nUOGhCjl
# +QIDAQABo4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYD
# VR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI
# AYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQW
# BBSfVywDdw4oFZBmpWNe7k+SH3agWzBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8v
# Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2
# VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcw
# AYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8v
# Y2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hB
# MjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQA9rR4fdplb
# 4ziEEkfZQ5H2EdubTggd0ShPz9Pce4FLJl6reNKLkZd5Y/vEIqFWKt4oKcKz7wZm
# Xa5VgW9B76k9NJxUl4JlKwyjUkKhk3aYx7D8vi2mpU1tKlY71AYXB8wTLrQeh83p
# XnWwwsxc1Mt+FWqz57yFq6laICtKjPICYYf/qgxACHTvypGHrC8k1TqCeHk6u4I/
# VBQC9VK7iSpU5wlWjNlHlFFv/M93748YTeoXU/fFa9hWJQkuzG2+B7+bMDvmgF8V
# lJt1qQcl7YFUMYgZU1WM6nyw23vT6QSgwX5Pq2m0xQ2V6FJHu8z4LXe/371k5QrN
# 9FQBhLLISZi2yemW0P8ZZfx4zvSWzVXpAb9k4Hpvpi6bUe8iK6WonUSV6yPlMwer
# wJZP/Gtbu3CKldMnn+LmmRTkTXpFIEB06nXZrDwhCGED+8RsWQSIXZpuG4WLFQOh
# tloDRWGoCwwc6ZpPddOFkM2LlTbMcqFSzm4cd0boGhBq7vkqI1uHRz6Fq1IX7TaR
# QuR+0BGOzISkcqwXu7nMpFu3mgrlgbAW+BzikRVQ3K2YHcGkiKjA4gi4OA/kz1YC
# sdhIBHXqBzR0/Zd2QwQ/l4Gxftt/8wY3grcc/nS//TVkej9nmUYu83BDtccHHXKi
# bMs/yXHhDXNkoPIdynhVAku7aRZOwqw6pDCCBq4wggSWoAMCAQICEAc2N7ckVHzY
# R6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE
# AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3
# MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2
# IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
# AMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjz
# aPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3E
# F3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYnc
# fGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8O
# pWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROp
# VymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4i
# FNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmif
# tkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0
# UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9Ne
# S3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCj
# WAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTAS
# BgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57I
# bzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMC
# AYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUF
# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6
# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0
# MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG
# SAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAY
# LhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQx
# Z822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf
# 7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDV
# inF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7
# +6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJ
# D5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvk
# OHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJG
# nXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimG
# sJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38A
# C+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d
# 2zc4GqEr9u3WfPwwggWNMIIEdaADAgECAhAOmxiO+dAt5+/bUOIIQBhaMA0GCSqG
# SIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFz
# c3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBaFw0zMTExMDkyMzU5NTla
# MGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
# EHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9v
# dCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8
# MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauy
# efLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34Lz
# B4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+x
# embud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhA
# kHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1Lyu
# GwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2
# PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37A
# lLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD7
# 6GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/
# ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXA
# j6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIBNjAPBgNVHRMBAf8EBTAD
# AQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzAfBgNVHSMEGDAWgBRF
# 66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMCAYYweQYIKwYBBQUHAQEE
# bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB
# BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3Vy
# ZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0aHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDARBgNVHSAECjAI
# MAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0NcVec4X6CjdBs9thbX979X
# B72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnovLbc47/T/gLn4offyct4k
# vFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65ZyoUi0mcudT6cGAxN3J0TU
# 53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFWjuyk1T3osdz9HNj0d1pc
# VIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPFmCLBsln1VWvPJ6tsds5v
# Iy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9ztwGpn1eqXijiuZQxggOG
# MIIDggIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5j
# LjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBU
# aW1lU3RhbXBpbmcgQ0ECEAuuZrxaun+Vh8b56QTjMwQwDQYJYIZIAWUDBAICBQCg
# geEwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0y
# NTAzMjcwNTEyNDRaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFNvThe5i29I+e+T2
# cUhQhyTVhltFMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIHZ2n6jyYy8fQws6IzCu
# 1lZ1/tdz2wXWZbkFk5hDj5rbMD8GCSqGSIb3DQEJBDEyBDAxfVHEVBie6x4ZeKJQ
# yHf2L2bfjpjuF8/UxBuRPUa8Wv35lv79vhq5Uc7aA3DWDEwwDQYJKoZIhvcNAQEB
# BQAEggIAVS29WC5KplfIENIfCZtjC0JdG1qgRzoyjIqA40XYLf6ITTV7HZa8bRNk
# 9MCr/r1UZfGiwCZd2HrsEMzwMyidxiRckNj4diSmT0pmxk4E4kLCt4LPtsQWqvpn
# uaxnF6hWdmvawf7o1eCsRk4T/2z2BVQ2KYfMbZg+KupJjXfUC4CeomAKnFgbKYXM
# dR6cMzAJ6+XRWecSRwmRBNka+VwBkx0Nd0abCuOvckFlO/sYusHN7gH2aB520UkN
# hs32emjcb6ZEcanf+9b4EcgzI4Q4NQEL2XlyDAeFeIFmQgVU7kLo4kWmr3aWxl+d
# W7vlaXc5uHkUC9gPNvvVybDgFBULf7I6/hRcyTpLywzH/TfwEECfP7J+SUSeK/5B
# tHr24IInEO+Sjd4fihBmMK4o8mREPN2QMl1kMwWMqwu5p0SWZfkWpT8D4ugkWSCc
# djd5RpRLTPilCggZMqzZimdWjZJZlovmi2FVyxny01x/tcAJGpXPU0WBOpE1KNJm
# 1SsUF8L4tPNMB+kWfB0j5f5h64CvYC4eIKBUTDakzmmgQ4wvi+tSQw4HA+OUvnw9
# NqEwyhWOpLv1/e03bD4TOrppurU802aqZPb3m/tI1/R1+VTNx6Nn4w/g2fDQcPbz
# cwsf3i9zAo8sjYQrG52/yycuYS4d4vQF77jGHtg1QYD323HUZ34=
# SIG # End signature block