UMN-Infoblox.psm1
### # Copyright 2017 University of Minnesota, Office of Information Technology # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with Foobar. If not, see <http://www.gnu.org/licenses/>. ## Modules for infoblox # It is assumed that a Connection has already been established and the cookie is being passed to many of these functions. # Use 'Connect-Infoblox' to return a $cookie -- #region Connect-Infoblox Function Connect-Infoblox{ <# .SYNOPSIS Core function - retrieve cookie for API access to infoblox .DESCRIPTION .PARAMETER InfobloxCred PS credential of user that has access .PARAMETER uriBase FQDN of infoblox host including version, example 'https://myhost.mycompany.com/wapi/v1.7.1' .PARAMETER SkipCertificateCheck Ignore bad SSL Certificates .EXAMPLE Connect-Infoblox -InfobloxCreds $infobloxCreds -uriBase $uriBase .NOTES For legacy automation systems dealing with cookies - -UseBasicParsing is included on the InvokeWebRequest - needed parsing for Orchestrator #> [CmdletBinding()] param( [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential]$InfobloxCreds, [parameter(Mandatory)] [string]$uriBase, [switch]$SkipCertificateCheck ) if ($SkipCertificateCheck -and $PSVersionTable.PSVersion.Major -lt 6){ add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy } $uri = "$uriBase/grid" if ($SkipCertificateCheck -and $PSVersionTable.PSVersion.Major -eq 6){$grid = Invoke-WebRequest -uri $uri -Method Get -Credential $InfobloxCreds -SessionVariable cookie -UseBasicParsing -SkipCertificateCheck} else{$grid = Invoke-WebRequest -uri $uri -Method Get -Credential $InfobloxCreds -SessionVariable cookie -UseBasicParsing} return ($cookie) } #endregion #region Get-InfobloxAlias Function Get-InfobloxAlias{ <# .SYNOPSIS Get Alias by FQDN .DESCRIPTION .EXAMPLE Get-InfobloxAlias -cookie $cookie -uriBase $uriBase -alias $alias .NOTES General notes #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$alias ) $uri = "$uriBase/record:cname?name:=$alias" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxHost Function Get-InfobloxHost{ <# .SYNOPSIS Get host by FQDN .DESCRIPTION Get host by FQDN .EXAMPLE Get-InfobloxHost -cookie $cookie -uriBase $uriBase -host_name $host_name .NOTES General notes #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$host_name ) $host_name = $host_name.ToLower() $uri = "$uriBase/record:host?name=$host_name&_return_fields=aliases,ipv4addrs,ipv6addrs" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxIPv4Net Function Get-InfobloxIPv4Net{ <# .SYNOPSIS Get IPv4 Network .DESCRIPTION Get a network stack from infoblox .EXAMPLE Get-InflobloxIPv4Net -cookie $cookie -uriBase $uriBase -ipv4Net $ipv4net .NOTES General notes #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv4Net ) $uri = "$uriBase/network?network=$ipv4Net" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxIPv4IP Function Get-InfobloxIPv4IP{ <# .SYNOPSIS Get reference to specific IPv4 address .DESCRIPTION .EXAMPLE Get-InflobloxIPv4IP -cookie $cookie -uriBase $uriBase -ipv4Address $ipv4Address .NOTES Check 'types' and look for HOST (NOT BULKHOST). If types contains HOST, its in use #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv4Address ) $uri = "$uriBase/ipv4address?ip_address=$ipv4Address" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxIPv4IPs Function Get-InfobloxIPv4IPs{ <# .SYNOPSIS Get reference to specific IPv4 network .DESCRIPTION Get all Hosts in a specific IPv4 Network .EXAMPLE Get-InfobloxIPv4ips -cookie $cookie -uriBase $uriBase -ipv4net $ipv4net .NOTES #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv4Net ) $uri = "$uriBase/ipv4address?network=$ipv4Net" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxIPv4Available Function Get-InfobloxIPv4Available{ <# .SYNOPSIS Get an available IPv4 address .DESCRIPTION Check for, and retrieve an available IPv4 address .EXAMPLE Get-InfobloxIP4Available -cookie $cookie -uriBase $uriBase -ipv4net $ipv4net -domainSuffix -$domainSuffix .NOTES #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv4Net, [ValidateNotNullOrEmpty()] [string]$domainSuffix ) $ipv4IPs = Get-InfobloxIPv4IPs -cookie $cookie -uriBase $uriBase -ipv4Net $ipv4Net $ipFound = $false foreach ($ip in $ipv4IPs){ if ($ip.types -notcontains "HOST" -and $ip.lease_state -eq "FREE") # IF it returns a single entry this should be the bulk host. < 1 = router, >1 its tied to host record so don't touch it { $ipFound = $true return $ip.ip_address } } if(-not $ipFound){return "unable to find IPv4 Address, exiting"} } #endregion #region Get-InfobloxIPv6IP Function Get-InfobloxIPv6IP{ <# .SYNOPSIS Get reference to specific IPv6 address .DESCRIPTION .EXAMPLE Get-InflobloxIPv6IP -cookie $cookie -uriBase $uriBase -ipv6Address $ipv6Address .NOTES #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv6address ) $uri = "$uriBase/record:host_ipv6addr?ipv6addr=$ipv6address" Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie } #endregion #region Get-InfobloxIPbyMac function Get-InfobloxIPbyMac { <# .SYNOPSIS Get IP information by MAC address .DESCRIPTION .EXAMPLE Get-InfobloxIPbyMac -cookie $cookie -uriBase $uriBase -ipv4net $ipv4net -mac $mac .NOTES #> [CmdletBinding()] param( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$ipv4Net, [ValidatePattern("([a-zA-Z0-9]{2}:){5}[a-zA-Z0-9]{2}")] [string]$mac ) $uri = "$uriBase/ipv4address?network=$ipv4Net&mac_address=$mac" $ipv4IPs = Invoke-RestMethod -uri $uri -Method Get -WebSession $cookie $activeIP = $ipv4IPs | Where-Object {$_.lease_state -eq 'ACTIVE'} if ($activeIP -ne $null){return ($activeIP.ip_address)} else{throw "Failed to get single IP info $ipv4IPs"} } #endregion #region New-InfobloxHost Function New-InfobloxHost{ <# .SYNOPSIS Create a new Host object with IPv4 and IPv6 Address .DESCRIPTION .EXAMPLE New-InfobloxHost -cookie $cookie -uribase $uriBase -host_name $host_name -new_IPv4 $new_ipV4 -new_IPv6 $new_ipv6 -ipv4net $ipv4net .NOTES Use other module commands to generate a list of IP's to associate to a new host entry. #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$host_name, [ValidateNotNullOrEmpty()] [string]$new_IPv4, [string]$new_IPv6, [ValidateNotNullOrEmpty()] [string]$ipv4Net ) $host_name = $host_name.ToLower() $uri = "$uriBase/record:host" if ($new_IPv6) { $JSON = @{name=$host_name;ipv4addrs=@(@{ipv4addr=$new_IPv4;configure_for_dhcp=$true;match_client="RESERVED"}); ipv6addrs=@(@{ipv6addr=$new_IPv6}); extattrs=@{Custom1=@{value=$ipv4Net};Custom2=@{value="default 2 hour"}}} | ConvertTo-Json } else { $JSON = @{name=$host_name;ipv4addrs=@(@{ipv4addr=$new_IPv4;configure_for_dhcp=$true;match_client="RESERVED"}); extattrs=@{Custom1=@{value=$ipv4Net};Custom2=@{value="default 2 hour"}}} | ConvertTo-Json } Invoke-RestMethod -Uri $uri -Body $JSON -ContentType "application/json" -Method Post -WebSession $cookie } #endregion #region New-InfobloxDhcpReservation Function New-InfobloxDhcpReservation{ <# .SYNOPSIS Create a new host object for doing DHCP reservations .DESCRIPTION For use with DHCP reservations by mac address .EXAMPLE New-InfobloxDhcpReservation -cookie $cookie -uriBase $uriBase -host_name $host_name -new_IPv4 $new_ipV4 -ipv4Net $ipv4net -mac $mac .NOTES #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$host_name, [ValidatePattern("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")] [string]$new_IPv4, [ValidateNotNullOrEmpty()] [string]$ipv4Net, [ValidatePattern("([a-zA-Z0-9]{2}:){5}[a-zA-Z0-9]{2}")] [string]$mac ) $host_name = $host_name.ToLower() $uri = "$uriBase/record:host" $JSON = @{name=$host_name;ipv4addrs=@(@{ipv4addr=$new_IPv4;configure_for_dhcp=$true;match_client="MAC_ADDRESS";mac=$mac}); extattrs=@{Custom1=@{value=$ipv4Net};Custom2=@{value="default 2 hour"}}} | ConvertTo-Json Invoke-RestMethod -Uri $uri -Body $JSON -ContentType "application/json" -Method Post -WebSession $cookie } #endregion #region Remove-InfobloxHost Function Remove-InfobloxHost{ <# .SYNOPSIS Remove Host Record .DESCRIPTION .EXAMPLE Remove-InfobloxHost -cookie $cookie -uriBase $uriBase -host_name $host_name .NOTES General notes #> ## [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$host_name ) $host_name = $host_name.ToLower() ## Validate Host exists $ibHost = Get-InfobloxHost -cookie $cookie -uriBase $uriBase -host_name $host_name if ($ibHost -eq $null){throw "Infoblox Host Doesn't Exist"} # Aliases must be removed before removing the host record if ($ibHost.aliases){}## waiting for enough permissions to see all the aliases and remove them $host_ref = $ibHost._ref $uri = "$uriBase/$host_ref" #validate response if ((Invoke-RestMethod -uri $uri -Method Delete -WebSession $cookie) -ne $host_ref){throw "Infoblox Delete Failed"} } #endregion #region Set-InfobloxHostIPv6 Function Set-InfobloxHostIPv6 { <# .SYNOPSIS Set IPv6 Address of Host Record .DESCRIPTION Set IPv6 Address of Host Record .PARAMETER cookie See connect-infoblox function to get authentication cookie .PARAMETER host_name The FQDN Host name in infoblox to be updated. .PARAMETER ipv6address The IPv6 address to be set for an AAAA record. .PARAMETER uriBase The base URI for your infoblox instance, such as https://fqdn/wapi/version .EXAMPLE Set-InfobloxHostIPv6 -cookie $cookie -uriBase $uriBase -host_name $host_name -ipv6Address .NOTES General notes #> [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [ValidateNotNullOrEmpty()] [string]$ipv6Address, [ValidateNotNullOrEmpty()] [string]$uriBase, [ValidateNotNullOrEmpty()] [string]$host_name ) Begin { $hostinfo = get-infobloxhost -cookie $cookie -uriBase $uriBase -host_name $host_name $hostref = $hostinfo._ref $uri = "$uriBase/$hostref" $JSON = @{ipv6addrs=@(@{ipv6addr=$ipv6Address})} | ConvertTo-Json } Process { $response = Invoke-RestMethod -Uri $uri -Body $JSON -ContentType "application/json" -Method Put -WebSession $cookie } End { return $response } } #endregion Function Get-InfobloxNetwork { <# .SYNOPSIS Get a network .DESCRIPTION Get a specified object from the Infoblox .PARAMETER Cookie Infoblox web session cookie .PARAMETER Network CIDR to get or search .PARAMETER UriBase The base Uri for the Infoblox including API version .EXAMPLE Get-InfobloxNetwork -cookie $cookie -uriBase $uriBase -network '10.0.0.0/25' _ref : network/asdf98a7kh5897afj98f7i2uh982hfakufh:10.0.0.0/25/default network : 10.0.0.0/25 network_view : default .EXAMPLE Get-InfobloxNetwork -cookie $cookie -uriBase $uriBase -network '10.50.' _ref : network/asdf98a7kh5897afj98f7i2uh982hfakufh:10.50.0.0/24/default network : 10.50.0.0/24 network_view : default _ref : network/asdf98a7kh5897afj98f7i2uh982hfakufh:10.50.1.0/24/default network : 10.50.1.0/24 network_view : default _ref : network/asdf98a7kh5897afj98f7i2uh982hfakufh:10.50.2.0/24/default network : 10.50.2.0/24 network_view : default ... #> [cmdletbinding()] param( [parameter(Mandatory)] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [parameter(Mandatory)] [string]$Network, [parameter(Mandatory)] [string]$uriBase ) Begin{ $uri="$uriBase/network?network~=$network"} Process{ $Return = Invoke-RestMethod -Method Get -Uri $uri -WebSession $cookie } End{ return $return } } Function Get-InfobloxNetworkExtAttributes { <# .SYNOPSIS Get network extensible attributes .DESCRIPTION Get extension properties for a network .PARAMETER Cookie Infoblox web session cookie .PARAMETER Network CIDR to get properties for. Calls Get-InfobloxNetwork - will return multiple networks if a CIDR is not specific. .PARAMETER UriBase The base Uri for the Infoblox including API version .EXAMPLE $test = Get-InfobloxNetworkExtAttributes -cookie $cookie -uriBase $uriBase -network '10.50.0.0/24' $test.extattrs |format-list _ref : network/adsfa98sdf7a9osfj98ag7qouijht984jh9:10.50.0.0/24/default extattrs : @{Location=; Owner=} network : 10.50.0.0/24 network_container : 10.50.0.0/16 network_view : default $test.extattrs |format-list Location : @{value=AWS} Owner : @{value=HSS} #> [cmdletbinding()] param( [parameter(Mandatory)] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [parameter(Mandatory)] [string]$Network, [string]$properties = "extattrs,network,network_view,network_container,comment", [parameter(Mandatory)] [string]$uriBase ) Begin{ $networkRefs = Get-InfobloxNetwork -cookie $cookie -Network $network -uriBase $uriBase $allData = @() } Process{ Foreach($item in $networkRefs){ $ref, $uri = $Null, $Null $ref = $item._ref $uri = "$uriBase/$ref`?_return_fields=$properties" $test = Invoke-RestMethod -Method Get -Uri $uri -WebSession $cookie $allData+=$test } } End{ return $allData } } Function Set-InfobloxNetworkExtAttributes{ <# .SYNOPSIS Set extensible attributes .DESCRIPTION Get extension properties for a network .PARAMETER Cookie Infoblox web session cookie .PARAMETER ExtAttribute The extensible attribute to set. Provide a hashtable in format $extAttributes = @{ "extattrs" = @{ "$ExtAttributeKey" = @{ "value"="$ExtAttributeValue"}; "$extAttributeKey2" = @{ "value"="$extAttributevalue2" } } } Add additional key value pairs as needed. .PARAMETER NetworkRef See get-infobloxNetwork to get object reference. .PARAMETER UriBase The base Uri for the Infoblox including API version. #> [cmdletbinding()] param( [parameter(Mandatory)] [Microsoft.PowerShell.Commands.WebRequestSession]$cookie, [parameter(Mandatory)] [string]$NetworkRef, [parameter(Mandatory)] [hashtable]$ExtAttribute, [parameter(Mandatory)] [string]$uriBase ) Begin{ $body = $ExtAttribute |convertto-json $uri = "$uriBase/$networkRef`?_return_fields=extattrs&_return_as_object=1" } Process{ $return = Invoke-RestMethod -Method Put -Uri $uri -body $body -contentType 'application/json' -WebSession $cookie $results = $return.result } End{ return $results } } Export-ModuleMember -Function * # SIG # Begin signature block # MIIfBwYJKoZIhvcNAQcCoIIe+DCCHvQCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUzpdY0rPmmIpVIc1ySr9Xrg5q # 5TGgghoTMIIEhDCCA2ygAwIBAgIQQhrylAmEGR9SCkvGJCanSzANBgkqhkiG9w0B # AQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNV # BAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRU # cnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTA1MDYwNzA4MDkxMFoXDTIwMDUzMDEw # NDgzOFowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2Fs # dCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8G # A1UECxMYaHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNF # UkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6q # gT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x # 2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ # w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbH # d2pBnqcP1/vulBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh # 2JU022R5KP+6LhHC5ehbkkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzT # bafc8H9vg2XiaquHhnUCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rE # JlTvA73gJMtUGjAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwDgYDVR0P # AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQG # A1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVz # dEV4dGVybmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGG # GWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEFBQADggEBAE1C # L6bBiusHgJBYRoz4GTlmKjxaLG3P1NmHVY15CxKIe0CP1cf4S41VFmOtt1fcOyu9 # 08FPHgOHS0Sb4+JARSbzJkkraoTxVHrUQtr802q7Zn7Knurpu9wHx8OSToM8gUmf # ktUyCepJLqERcZo20sVOaLbLDhslFq9s3l122B9ysZMmhhfbGN6vRenf+5ivFBjt # pF72iZRF8FUESt3/J90GSkD2tLzx5A+ZArv9XQ4uKMG+O18aP5cQhLwWPtijnGMd # ZstcX9o+8w8KCTUi29vAPwD55g1dZ9H9oB4DK9lA977Mh2ZUgKajuPUZYtXSJrGY # Ju6ay0SnRVqBlRUa9VEwggTmMIIDzqADAgECAhBiXE2QjNVC+6supXM/8VQZMA0G # CSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNV # BAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdv # cmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMU # VVROLVVTRVJGaXJzdC1PYmplY3QwHhcNMTEwNDI3MDAwMDAwWhcNMjAwNTMwMTA0 # ODM4WjB6MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVy # MRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEg # MB4GA1UEAxMXQ09NT0RPIFRpbWUgU3RhbXBpbmcgQ0EwggEiMA0GCSqGSIb3DQEB # AQUAA4IBDwAwggEKAoIBAQCqgvGEqVvYcbXSXSvt9BMgDPmb6dGPdF5u7uspSNjI # vizrCmFgzL2SjXzddLsKnmhOqnUkcyeuN/MagqVtuMgJRkx+oYPp4gNgpCEQJ0Ca # WeFtrz6CryFpWW1jzM6x9haaeYOXOh0Mr8l90U7Yw0ahpZiqYM5V1BIR8zsLbMaI # upUu76BGRTl8rOnjrehXl1/++8IJjf6OmqU/WUb8xy1dhIfwb1gmw/BC/FXeZb5n # OGOzEbGhJe2pm75I30x3wKoZC7b9So8seVWx/llaWm1VixxD9rFVcimJTUA/vn9J # AV08m1wI+8ridRUFk50IYv+6Dduq+LW/EDLKcuoIJs0ZAgMBAAGjggFKMIIBRjAf # BgNVHSMEGDAWgBTa7WR0FJwUPKvdmam9WyhNizzJ2DAdBgNVHQ4EFgQUZCKGtkqJ # yQQP0ARYkiuzbj0eJ2wwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C # AQAwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMEIGA1Ud # HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZp # cnN0LU9iamVjdC5jcmwwdAYIKwYBBQUHAQEEaDBmMD0GCCsGAQUFBzAChjFodHRw # Oi8vY3J0LnVzZXJ0cnVzdC5jb20vVVROQWRkVHJ1c3RPYmplY3RfQ0EuY3J0MCUG # CCsGAQUFBzABhhlodHRwOi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEB # BQUAA4IBAQARyT3hBeg7ZazJdDEDt9qDOMaSuv3N+Ntjm30ekKSYyNlYaDS18Ash # U55ZRv1jhd/+R6pw5D9eCJUoXxTx/SKucOS38bC2Vp+xZ7hog16oYNuYOfbcSV4T # p5BnS+Nu5+vwQ8fQL33/llqnA9abVKAj06XCoI75T9GyBiH+IV0njKCv2bBS7vzI # 7bec8ckmONalMu1Il5RePeA9NbSwyVivx1j/YnQWkmRB2sqo64sDvcFOrh+RMrjh # JDt77RRoCYaWKMk7yWwowiVp9UphreAn+FOndRWwUTGw8UH/PlomHmB+4uNqOZrE # 6u4/5rITP1UDBE0LkHLU6/u8h5BRsjgZMIIE/jCCA+agAwIBAgIQK3PbdGMRTFpb # MkryMFdySTANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJHQjEbMBkGA1UECBMS # R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD # T01PRE8gQ0EgTGltaXRlZDEgMB4GA1UEAxMXQ09NT0RPIFRpbWUgU3RhbXBpbmcg # Q0EwHhcNMTkwNTAyMDAwMDAwWhcNMjAwNTMwMTA0ODM4WjCBgzELMAkGA1UEBhMC # R0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9y # ZDEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDDCJTZWN0aWdvIFNI # QS0xIFRpbWUgU3RhbXBpbmcgU2lnbmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A # MIIBCgKCAQEAv1I2gjrcdDcNeNV/FlAZZu26GpnRYziaDGayQNungFC/aS42Lwpn # P0ChSopjNZvQGcx0qhcZkSu1VSAZ+8AaOm3KOZuC8rqVoRrYNMe4iXtwiHBRZmns # d/7GlHJ6zyWB7TSCmt8IFTcxtG2uHL8Y1Q3P/rXhxPuxR3Hp+u5jkezx7M5ZBBF8 # rgtgU+oq874vAg/QTF0xEy8eaQ+Fm0WWwo0Si2euH69pqwaWgQDfkXyVHOaeGWTf # dshgRC9J449/YGpFORNEIaW6+5H6QUDtTQK0S3/f4uA9uKrzGthBg49/M+1BBuJ9 # nj9ThI0o2t12xr33jh44zcDLYCQD3npMqwIDAQABo4IBdDCCAXAwHwYDVR0jBBgw # FoAUZCKGtkqJyQQP0ARYkiuzbj0eJ2wwHQYDVR0OBBYEFK7u2WC6XvUsARL9jo2y # VXI1Rm/xMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM # MAoGCCsGAQUFBwMIMEAGA1UdIAQ5MDcwNQYMKwYBBAGyMQECAQMIMCUwIwYIKwYB # BQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMEIGA1UdHwQ7MDkwN6A1oDOG # MWh0dHA6Ly9jcmwuc2VjdGlnby5jb20vQ09NT0RPVGltZVN0YW1waW5nQ0FfMi5j # cmwwcgYIKwYBBQUHAQEEZjBkMD0GCCsGAQUFBzAChjFodHRwOi8vY3J0LnNlY3Rp # Z28uY29tL0NPTU9ET1RpbWVTdGFtcGluZ0NBXzIuY3J0MCMGCCsGAQUFBzABhhdo # dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAen+pStKw # pBwdDZ0tXMauWt2PRR3wnlyQ9l6scP7T2c3kGaQKQ3VgaoOkw5mEIDG61v5MzxP4 # EPdUCX7q3NIuedcHTFS3tcmdsvDyHiQU0JzHyGeqC2K3tPEG5OfkIUsZMpk0uRlh # dwozkGdswIhKkvWhQwHzrqJvyZW9ljj3g/etfCgf8zjfjiHIcWhTLcuuquIwF4Mi # KRi14YyJ6274fji7kE+5Xwc0EmuX1eY7kb4AFyFu4m38UnnvgSW6zxPQ+90rzYG2 # V4lO8N3zC0o0yoX/CLmWX+sRE+DhxQOtVxzhXZIGvhvIPD+lIJ9p0GnBxcLJPufF # cvfqG5bilK+GLjCCBawwggSUoAMCAQICEHJNXiAT1cKRQFXzfFSJVHEwDQYJKoZI # hvcNAQELBQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1JMRIwEAYDVQQHEwlB # bm4gQXJib3IxEjAQBgNVBAoTCUludGVybmV0MjERMA8GA1UECxMISW5Db21tb24x # JTAjBgNVBAMTHEluQ29tbW9uIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTcxMjE0 # MDAwMDAwWhcNMjAxMjEzMjM1OTU5WjCByzELMAkGA1UEBhMCVVMxDjAMBgNVBBEM # BTU1NDU1MRIwEAYDVQQIDAlNaW5uZXNvdGExFDASBgNVBAcMC01pbm5lYXBvbGlz # MRgwFgYDVQQJDA8xMDAgVW5pb24gU3QgU0UxIDAeBgNVBAoMF1VuaXZlcnNpdHkg # b2YgTWlubmVzb3RhMSQwIgYDVQQLDBtDb21wdXRlciBhbmQgRGV2aWNlIFN1cHBv # cnQxIDAeBgNVBAMMF1VuaXZlcnNpdHkgb2YgTWlubmVzb3RhMIIBIjANBgkqhkiG # 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwk6kLE9u+tWv0JUkIJSn5pWfa09g6cqFLucC # XomNj9NYj8t+JfPna3gC6LHv3OQAUDHOoC5H+8N3ea7qVGYIiwPRHzXOGqG/tVai # U5s5hG3vBhfRX8W1/2g4/hpgeXUzrxYn/2c5SOGGy0MU1ZJyUSFEdsjXHEV7HXK4 # qmFGV9RJxtiLZH1qUldCglxcj7zw0QnUdG6oAxpwTCeVp057/WXbnIR8a0gPse+y # /new5+CBUGTAvrw6K2BrJQVsdIIVn/q+BbcZxh9PpeZfTtsi6lgkvy0bUWtl5sSp # d75+hvw4Sl3HAaWZtoWN7LPmbDbbVRO2Arv4doh4Chod4wJ5xQIDAQABo4IB2DCC # AdQwHwYDVR0jBBgwFoAUrjUjF///Bj2cUOCMJGUzHnAQiKIwHQYDVR0OBBYEFF4L # EhElVUvT8n5txOJSNAczooSAMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA # MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBmBgNVHSAE # XzBdMFsGDCsGAQQBriMBBAMCATBLMEkGCCsGAQUFBwIBFj1odHRwczovL3d3dy5p # bmNvbW1vbi5vcmcvY2VydC9yZXBvc2l0b3J5L2Nwc19jb2RlX3NpZ25pbmcucGRm # MEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuaW5jb21tb24tcnNhLm9yZy9J # bkNvbW1vblJTQUNvZGVTaWduaW5nQ0EuY3JsMH4GCCsGAQUFBwEBBHIwcDBEBggr # BgEFBQcwAoY4aHR0cDovL2NydC5pbmNvbW1vbi1yc2Eub3JnL0luQ29tbW9uUlNB # Q29kZVNpZ25pbmdDQS5jcnQwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmluY29t # bW9uLXJzYS5vcmcwGQYDVR0RBBIwEIEOb2l0bXB0QHVtbi5lZHUwDQYJKoZIhvcN # AQELBQADggEBAENRlesMKmBaZ0g68lttYEMtaPiz+DaNpOlXBs1gH66aghB1aP6i # iRJcFVasGLUVFncdG1xbw503LTrBUc5PECMVDVF7KKCfHA1OeFV9vOWyvdVgbe3p # aDy1sj4CADO2D0gnxcGiZoFhEZiBkTvSsj4S3GXZEvoFHJxJLw2kvdLnzy0gH/b/ # b/yblwA1fKXw4locUpDM6qTwM7SiKgkQ5W7/280EYu8BI6c8rpiJmqM1tZLcpswu # avB00T52Y+ZZmz3tMMVgFHn9pFFltYr3s3bEek7I6pU8unISbiyQzxqhIUKaBi8h # y8LgoY5UnGjX5jHsIvINzms+JX5Ity02sL0wggXrMIID06ADAgECAhBl4eLj1d5Q # RYXzJiSABeLUMA0GCSqGSIb3DQEBDQUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKTmV3IEplcnNleTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRo # ZSBVU0VSVFJVU1QgTmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0 # aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNDA5MTkwMDAwMDBaFw0yNDA5MTgyMzU5 # NTlaMHwxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNSTESMBAGA1UEBxMJQW5uIEFy # Ym9yMRIwEAYDVQQKEwlJbnRlcm5ldDIxETAPBgNVBAsTCEluQ29tbW9uMSUwIwYD # VQQDExxJbkNvbW1vbiBSU0EgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEAwKAvix56u2p1rPg+3KO6OSLK86N25L99MCfmutOY # MlYjXAaGlw2A6O2igTXrC/Zefqk+aHP9ndRnec6q6mi3GdscdjpZh11emcehsrip # hHMMzKuHRhxqx+85Jb6n3dosNXA2HSIuIDvd4xwOPzSf5X3+VYBbBnyCV4RV8zj7 # 8gw2qblessWBRyN9EoGgwAEoPgP5OJejrQLyAmj91QGr9dVRTVDTFyJG5XMY4Drk # N3dRyJ59UopPgNwmucBMyvxR+hAJEXpXKnPE4CEqbMJUvRw+g/hbqSzx+tt4z9mJ # mm2j/w2nP35MViPWCb7hpR2LB8W/499Yqu+kr4LLBfgKCQIDAQABo4IBWjCCAVYw # HwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFK41Ixf/ # /wY9nFDgjCRlMx5wEIiiMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/ # AgEAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNV # HR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0 # UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8G # CCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNB # QWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVz # dC5jb20wDQYJKoZIhvcNAQENBQADggIBAEYstn9qTiVmvZxqpqrQnr0Prk41/PA4 # J8HHnQTJgjTbhuET98GWjTBEE9I17Xn3V1yTphJXbat5l8EmZN/JXMvDNqJtkyOh # 26owAmvquMCF1pKiQWyuDDllxR9MECp6xF4wnH1Mcs4WeLOrQPy+C5kWE5gg/7K6 # c9G1VNwLkl/po9ORPljxKKeFhPg9+Ti3JzHIxW7LdyljffccWiuNFR51/BJHAZIq # UDw3LsrdYWzgg4x06tgMvOEf0nITelpFTxqVvMtJhnOfZbpdXZQ5o1TspxfTEVOQ # Asp05HUNCXyhznlVLr0JaNkM7edgk59zmdTbSGdMq8Ztuu6VyrivOlMSPWmay5Mj # vwTzuNorbwBv0DL+7cyZBp7NYZou+DoGd1lFZN0jU5IsQKgm3+00pnnJ67crdFwf # z/8bq3MhTiKOWEb04FT3OZVp+jzvaChHWLQ8gbCORgClaZq1H3aqI7JeRkWEEEp6 # Tv4WAVsr/i7LoXU72gOb8CAzPFqwI4Excdrxp0I4OXbECHlDqU4sTInqwlMwofmx # eO4u94196qIqJQl+8Sykl06VktqMux84Iw3ZQLH08J8LaJ+WDUycc4OjY61I7FGx # CDkbSQf3npXeRFm0IBn8GiW+TRDk6J2XJFLWEtVZmhboFlBLoUlqHUCKu0QOhU/+ # AEOqnY98j2zRMYIEXjCCBFoCAQEwgZAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgT # Ak1JMRIwEAYDVQQHEwlBbm4gQXJib3IxEjAQBgNVBAoTCUludGVybmV0MjERMA8G # A1UECxMISW5Db21tb24xJTAjBgNVBAMTHEluQ29tbW9uIFJTQSBDb2RlIFNpZ25p # bmcgQ0ECEHJNXiAT1cKRQFXzfFSJVHEwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcC # AQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYB # BAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFDLRFwYfyb7q # bJEZ0RR8HGN+u8etMA0GCSqGSIb3DQEBAQUABIIBAFZs7QWSK02xTwoC4mZeZqQx # yaffKrahgBJ3P59kPnD7dbBO6EaNCdPjUEHxqq8RMKcnJ/lBNdqS+2n5BrDUOUjJ # /qQmeW+6CTW37kw3XuIsTWT7TwxSm4WUp8du5Zd83Y8bl8xHF6NQuMAiwKtHukq/ # qWUUrMXj93FCCo6uUfbnoWWZrQFxaY9JlcyV5DMkfslygLZLRnsMWyu+zDGV5F6O # 2CwVVXAJCev6rUVMe/xbBd1TxqYPnQrfPSd8iF+Caza/Sighec09auxGrhE65HNq # Jve7HtwO46k/mG5BLqZInMlqIIGS8xcgm9SwuU1Jb4pFR3SA/D/QPDdhuSOAuqKh # ggIoMIICJAYJKoZIhvcNAQkGMYICFTCCAhECAQEwgY4wejELMAkGA1UEBhMCR0Ix # GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEa # MBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxIDAeBgNVBAMTF0NPTU9ETyBUaW1l # IFN0YW1waW5nIENBAhArc9t0YxFMWlsySvIwV3JJMAkGBSsOAwIaBQCgXTAYBgkq # hkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMDA0MzAyMTI0 # MTRaMCMGCSqGSIb3DQEJBDEWBBQ3Q7zNH+43jrdW3+KRFpR3SyXJgjANBgkqhkiG # 9w0BAQEFAASCAQChUy2l90UrE8k3zvSUJkMtYGXkVjWeiT2vXV6iztlX7b8r4LMf # 64C02dIaKql5/Boz2lnB+nhJ1ufrAhbDPm3Kv16Xrk5RsJkrbYdAY/5n2kGTBesX # lT7WbLK3ztrcbdqN7JqCGsr+t1mUF9MyF5RVQm1uW/PTtMsbpHv4e0TN0Sq5XEu8 # Ip3tvwy8mBJUtoVuYUjBStoHDnHRwQW8kxbhJzvqQxvl+1eisxb1jI0SwaNZBani # m0TtBSxM66FqiG2W03Hs5bxCgal4lf4TDMpJKZIhXUCFbmd0LLQUXfGASapG+d1g # NPtYfa2o984dRPEDWUOdb/RaUpA55kpeCNiU # SIG # End signature block |