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" 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 Export-ModuleMember -Function * # SIG # Begin signature block # MIIaxgYJKoZIhvcNAQcCoIIatzCCGrMCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU5LNMEgy74o26LmxizC7cPtOl # jlegghW3MIIEmTCCA4GgAwIBAgIPFojwOSVeY45pFDkH5jMLMA0GCSqGSIb3DQEB # BQUAMIGVMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQg # TGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNV # BAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEdMBsGA1UEAxMUVVROLVVTRVJG # aXJzdC1PYmplY3QwHhcNMTUxMjMxMDAwMDAwWhcNMTkwNzA5MTg0MDM2WjCBhDEL # MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE # BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKjAoBgNVBAMT # IUNPTU9ETyBTSEEtMSBUaW1lIFN0YW1waW5nIFNpZ25lcjCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBAOnpPd/XNwjJHjiyUlNCbSLxscQGBGue/YJ0UEN9 # xqC7H075AnEmse9D2IOMSPznD5d6muuc3qajDjscRBh1jnilF2n+SRik4rtcTv6O # KlR6UPDV9syR55l51955lNeWM/4Og74iv2MWLKPdKBuvPavql9LxvwQQ5z1IRf0f # aGXBf1mZacAiMQxibqdcZQEhsGPEIhgn7ub80gA9Ry6ouIZWXQTcExclbhzfRA8V # zbfbpVd2Qm8AaIKZ0uPB3vCLlFdM7AiQIiHOIiuYDELmQpOUmJPv/QbZP7xbm1Q8 # ILHuatZHesWrgOkwmt7xpD9VTQoJNIp1KdJprZcPUL/4ygkCAwEAAaOB9DCB8TAf # BgNVHSMEGDAWgBTa7WR0FJwUPKvdmam9WyhNizzJ2DAdBgNVHQ4EFgQUjmstM2v0 # M6eTsxOapeAK9xI1aogwDgYDVR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwFgYD # VR0lAQH/BAwwCgYIKwYBBQUHAwgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny # bC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDA1BggrBgEF # BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w # DQYJKoZIhvcNAQEFBQADggEBALozJEBAjHzbWJ+zYJiy9cAx/usfblD2CuDk5oGt # Joei3/2z2vRz8wD7KRuJGxU+22tSkyvErDmB1zxnV5o5NuAoCJrjOU+biQl/e8Vh # f1mJMiUKaq4aPvCiJ6i2w7iH9xYESEE9XNjsn00gMQTZZaHtzWkHUxY93TYCCojr # QOUGMAu4Fkvc77xVCf/GPhIudrPczkLv+XZX4bcKBUCYWJpdcRaTcYxlgepv84n3 # +3OttOe/2Y5vqgtPJfO44dXddZhogfiqwNGAwsTEOYnB9smebNd0+dmX+E/CmgrN # Xo/4GengpZ/E8JIh5i15Jcki+cPwOoRXrToW9GOUEB1d0MYwggV3MIIEX6ADAgEC # AhAT6ihwW/Ts7Qw2YwmAYUM2MA0GCSqGSIb3DQEBDAUAMG8xCzAJBgNVBAYTAlNF # MRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJu # YWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJv # b3QwHhcNMDAwNTMwMTA0ODM4WhcNMjAwNTMwMTA0ODM4WjCBiDELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4w # HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVz # dCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzO # iZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwW # IJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YU # VD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1da # t//O+T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+ # UzeQc0PzMsNT79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/z # JSZrM233bkf6c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLa # qUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxb # gtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9A # qURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ # eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwID # AQABo4H0MIHxMB8GA1UdIwQYMBaAFK29mHo0tCb3+sQmVO8DveAky1QaMB0GA1Ud # DgQWBBRTeb9aqitKz1SA4dibwJ3ysgNmyzAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T # AQH/BAUwAwEB/zARBgNVHSAECjAIMAYGBFUdIAAwRAYDVR0fBD0wOzA5oDegNYYz # aHR0cDovL2NybC51c2VydHJ1c3QuY29tL0FkZFRydXN0RXh0ZXJuYWxDQVJvb3Qu # Y3JsMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNl # cnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAQEAk2X2N4OVD17Dghwf1nfnPIrA # qgnw6Qsm8eDCanWhx3nJuVJgyCkSDvCtA9YJxHbf5aaBladG2oJXqZWSxbaPAyJs # M3fBezIXbgfOWhRBOgUkG/YUBjuoJSQOu8wqdd25cEE/fNBjNiEHH0b/YKSR4We8 # 3h9+GRTJY2eR6mcHa7SPi8BuQ33DoYBssh68U4V93JChpLwt70ZyVzUFv7tGu25t # N5m2/yOSkcZuQPiPKVbqX9VfFFOs8E9h6vcizKdWC+K4NB8m2XsZBWg/ujzUOAai # 0+aPDuO0cW1AQsWEtECVK/RloEh59h2BY5adT3Xg+HzkjqnR8q2Ks4zHIc3C7zCC # BawwggSUoAMCAQICEHJNXiAT1cKRQFXzfFSJVHEwDQYJKoZIhvcNAQELBQAwfDEL # MAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1JMRIwEAYDVQQHEwlBbm4gQXJib3IxEjAQ # BgNVBAoTCUludGVybmV0MjERMA8GA1UECxMISW5Db21tb24xJTAjBgNVBAMTHElu # Q29tbW9uIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMTcxMjE0MDAwMDAwWhcNMjAx # MjEzMjM1OTU5WjCByzELMAkGA1UEBhMCVVMxDjAMBgNVBBEMBTU1NDU1MRIwEAYD # VQQIDAlNaW5uZXNvdGExFDASBgNVBAcMC01pbm5lYXBvbGlzMRgwFgYDVQQJDA8x # MDAgVW5pb24gU3QgU0UxIDAeBgNVBAoMF1VuaXZlcnNpdHkgb2YgTWlubmVzb3Rh # MSQwIgYDVQQLDBtDb21wdXRlciBhbmQgRGV2aWNlIFN1cHBvcnQxIDAeBgNVBAMM # F1VuaXZlcnNpdHkgb2YgTWlubmVzb3RhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A # MIIBCgKCAQEAwk6kLE9u+tWv0JUkIJSn5pWfa09g6cqFLucCXomNj9NYj8t+JfPn # a3gC6LHv3OQAUDHOoC5H+8N3ea7qVGYIiwPRHzXOGqG/tVaiU5s5hG3vBhfRX8W1 # /2g4/hpgeXUzrxYn/2c5SOGGy0MU1ZJyUSFEdsjXHEV7HXK4qmFGV9RJxtiLZH1q # UldCglxcj7zw0QnUdG6oAxpwTCeVp057/WXbnIR8a0gPse+y/new5+CBUGTAvrw6 # K2BrJQVsdIIVn/q+BbcZxh9PpeZfTtsi6lgkvy0bUWtl5sSpd75+hvw4Sl3HAaWZ # toWN7LPmbDbbVRO2Arv4doh4Chod4wJ5xQIDAQABo4IB2DCCAdQwHwYDVR0jBBgw # FoAUrjUjF///Bj2cUOCMJGUzHnAQiKIwHQYDVR0OBBYEFF4LEhElVUvT8n5txOJS # NAczooSAMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoG # CCsGAQUFBwMDMBEGCWCGSAGG+EIBAQQEAwIEEDBmBgNVHSAEXzBdMFsGDCsGAQQB # riMBBAMCATBLMEkGCCsGAQUFBwIBFj1odHRwczovL3d3dy5pbmNvbW1vbi5vcmcv # Y2VydC9yZXBvc2l0b3J5L2Nwc19jb2RlX3NpZ25pbmcucGRmMEkGA1UdHwRCMEAw # PqA8oDqGOGh0dHA6Ly9jcmwuaW5jb21tb24tcnNhLm9yZy9JbkNvbW1vblJTQUNv # ZGVTaWduaW5nQ0EuY3JsMH4GCCsGAQUFBwEBBHIwcDBEBggrBgEFBQcwAoY4aHR0 # cDovL2NydC5pbmNvbW1vbi1yc2Eub3JnL0luQ29tbW9uUlNBQ29kZVNpZ25pbmdD # QS5jcnQwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmluY29tbW9uLXJzYS5vcmcw # GQYDVR0RBBIwEIEOb2l0bXB0QHVtbi5lZHUwDQYJKoZIhvcNAQELBQADggEBAENR # lesMKmBaZ0g68lttYEMtaPiz+DaNpOlXBs1gH66aghB1aP6iiRJcFVasGLUVFncd # G1xbw503LTrBUc5PECMVDVF7KKCfHA1OeFV9vOWyvdVgbe3paDy1sj4CADO2D0gn # xcGiZoFhEZiBkTvSsj4S3GXZEvoFHJxJLw2kvdLnzy0gH/b/b/yblwA1fKXw4loc # UpDM6qTwM7SiKgkQ5W7/280EYu8BI6c8rpiJmqM1tZLcpswuavB00T52Y+ZZmz3t # MMVgFHn9pFFltYr3s3bEek7I6pU8unISbiyQzxqhIUKaBi8hy8LgoY5UnGjX5jHs # IvINzms+JX5Ity02sL0wggXrMIID06ADAgECAhBl4eLj1d5QRYXzJiSABeLUMA0G # CSqGSIb3DQEBDQUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNl # eTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1Qg # TmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1 # dGhvcml0eTAeFw0xNDA5MTkwMDAwMDBaFw0yNDA5MTgyMzU5NTlaMHwxCzAJBgNV # BAYTAlVTMQswCQYDVQQIEwJNSTESMBAGA1UEBxMJQW5uIEFyYm9yMRIwEAYDVQQK # EwlJbnRlcm5ldDIxETAPBgNVBAsTCEluQ29tbW9uMSUwIwYDVQQDExxJbkNvbW1v # biBSU0EgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB # CgKCAQEAwKAvix56u2p1rPg+3KO6OSLK86N25L99MCfmutOYMlYjXAaGlw2A6O2i # gTXrC/Zefqk+aHP9ndRnec6q6mi3GdscdjpZh11emcehsriphHMMzKuHRhxqx+85 # Jb6n3dosNXA2HSIuIDvd4xwOPzSf5X3+VYBbBnyCV4RV8zj78gw2qblessWBRyN9 # EoGgwAEoPgP5OJejrQLyAmj91QGr9dVRTVDTFyJG5XMY4DrkN3dRyJ59UopPgNwm # ucBMyvxR+hAJEXpXKnPE4CEqbMJUvRw+g/hbqSzx+tt4z9mJmm2j/w2nP35MViPW # Cb7hpR2LB8W/499Yqu+kr4LLBfgKCQIDAQABo4IBWjCCAVYwHwYDVR0jBBgwFoAU # U3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFK41Ixf//wY9nFDgjCRlMx5w # EIiiMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMGA1UdJQQM # MAoGCCsGAQUFBwMDMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8ESTBHMEWgQ6BB # hj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2VydGlmaWNh # dGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUFBzAChjNo # dHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1c3RDQS5j # cnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZI # hvcNAQENBQADggIBAEYstn9qTiVmvZxqpqrQnr0Prk41/PA4J8HHnQTJgjTbhuET # 98GWjTBEE9I17Xn3V1yTphJXbat5l8EmZN/JXMvDNqJtkyOh26owAmvquMCF1pKi # QWyuDDllxR9MECp6xF4wnH1Mcs4WeLOrQPy+C5kWE5gg/7K6c9G1VNwLkl/po9OR # PljxKKeFhPg9+Ti3JzHIxW7LdyljffccWiuNFR51/BJHAZIqUDw3LsrdYWzgg4x0 # 6tgMvOEf0nITelpFTxqVvMtJhnOfZbpdXZQ5o1TspxfTEVOQAsp05HUNCXyhznlV # Lr0JaNkM7edgk59zmdTbSGdMq8Ztuu6VyrivOlMSPWmay5MjvwTzuNorbwBv0DL+ # 7cyZBp7NYZou+DoGd1lFZN0jU5IsQKgm3+00pnnJ67crdFwfz/8bq3MhTiKOWEb0 # 4FT3OZVp+jzvaChHWLQ8gbCORgClaZq1H3aqI7JeRkWEEEp6Tv4WAVsr/i7LoXU7 # 2gOb8CAzPFqwI4Excdrxp0I4OXbECHlDqU4sTInqwlMwofmxeO4u94196qIqJQl+ # 8Sykl06VktqMux84Iw3ZQLH08J8LaJ+WDUycc4OjY61I7FGxCDkbSQf3npXeRFm0 # IBn8GiW+TRDk6J2XJFLWEtVZmhboFlBLoUlqHUCKu0QOhU/+AEOqnY98j2zRMYIE # eTCCBHUCAQEwgZAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1JMRIwEAYDVQQH # EwlBbm4gQXJib3IxEjAQBgNVBAoTCUludGVybmV0MjERMA8GA1UECxMISW5Db21t # b24xJTAjBgNVBAMTHEluQ29tbW9uIFJTQSBDb2RlIFNpZ25pbmcgQ0ECEHJNXiAT # 1cKRQFXzfFSJVHEwCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKEC # gAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG # CisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFLKbDHOAgWFdfQGzWUDFu1ELHqiV # MA0GCSqGSIb3DQEBAQUABIIBAJxZVJxMLux0DuWwgD2+9UQpyH1X4usy91tLvgLn # Ty0Flobvyx6LzDZ3XpiecnopUKullaO1rvS/A0mbDRuOJVVxZYaPJHsk8z8XJGDe # YjL1KeanOhAQQ3AtXh7McT8kCbxhxjdlRmct0SH89HmC1OiKJtIRc7uJr7VUmdSw # F+OHOiZEYUKDvSB4leeKpgz1m4TMrY6pM9F4hOPBSH9139xBahdqKYi/PqsOXTLq # S5Gr8U8rg1cu9rvdaRru7QEUTr4vcLr4fItfH44EbSnOf3gRYMjzYPEZuM+nx36w # wnyMOQHo4T8lrbAqsjM5+BM7MSAibvUvfnbiOihfGUXC8e2hggJDMIICPwYJKoZI # hvcNAQkGMYICMDCCAiwCAQEwgakwgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJV # VDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJV # U1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR0w # GwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdAIPFojwOSVeY45pFDkH5jMLMAkG # BSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJ # BTEPFw0xODAyMTYxOTE3MjFaMCMGCSqGSIb3DQEJBDEWBBSWiAY4cRG2LFCKyOdc # gba/kqaywTANBgkqhkiG9w0BAQEFAASCAQAE11GgBjuNRUuINZVnjzd992R79Kma # 7Qh6g+5Sw9WsTjmI0CC+mHwLcs7J7x4urqzK+mON1caNcLfik99A4ltG8DwpYWx0 # iVM2DPNZXTJN4sqk3vLL4HDc0PJYaAH9JuMJzL6/mP/47vtUd6YKN13uE9O+rKTI # 9gmnX54IWa4BcQgTbw6s7dEO2P4NhbBQcEYFaL2xKfEISoqg3M7h8KdiVBqV3go8 # fyK95fDXZvLsutxbIJmrZDyCW4S5zTnrbE5EK+m6Ltdqltk4Hm3HF5y7D5BoVVk0 # 3cqMKhSSsnLTq/EfogAr9/KEJBrHVdUfZtx29j5iAVlEsXqf3b/vqoRj # SIG # End signature block |