PowerInfoblox.psm1
function Get-IPAddressRangeInformation { <# .SYNOPSIS Provides information about IP Address range .DESCRIPTION Provides information about IP Address range .PARAMETER Network Network in form of IP/NetworkLength (e.g. 10.2.10.0/24') .PARAMETER IPAddress IP Address to use .PARAMETER NetworkLength Network length to use .PARAMETER CIDRObject CIDRObject to use .EXAMPLE $CidrObject = @{ Ip = '10.2.10.0' NetworkLength = 24 } Get-IPAddressRangeInformation -CIDRObject $CidrObject | Format-Table .EXAMPLE Get-IPAddressRangeInformation -Network '10.2.10.0/24' | Format-Table .EXAMPLE Get-IPAddressRangeInformation -IPAddress '10.2.10.0' -NetworkLength 24 | Format-Table .NOTES General notes #> [cmdletBinding(DefaultParameterSetName = 'Network')] param( [Parameter(ParameterSetName = 'Network', Mandatory)][string] $Network, [Parameter(ParameterSetName = 'IPAddress', Mandatory)][string] $IPAddress, [Parameter(ParameterSetName = 'IPAddress', Mandatory)][int] $NetworkLength, [Parameter(ParameterSetName = 'CIDR', Mandatory)][psobject] $CIDRObject ) $IPv4Regex = '(?:(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)' if ($Network) { $CIDRObject = @{ Ip = $Network.Split('/')[0] NetworkLength = $Network.Split('/')[1] } } elseif ($IPAddress -and $NetworkLength) { $CIDRObject = @{ Ip = $IPAddress NetworkLength = $NetworkLength } } elseif ($CIDRObject) { } else { Write-Error "Get-IPAddressRangeInformation - Invalid parameters specified" return } $o = [ordered] @{} $o.IP = [string] $CIDRObject.IP $o.BinaryIP = Convert-IPToBinary $o.IP if (-not $o.BinaryIP) { return } $o.NetworkLength = [int32] $CIDRObject.NetworkLength $o.SubnetMask = Convert-BinaryToIP ('1' * $o.NetworkLength).PadRight(32, '0') $o.BinarySubnetMask = ('1' * $o.NetworkLength).PadRight(32, '0') $o.BinaryNetworkAddress = $o.BinaryIP.SubString(0, $o.NetworkLength).PadRight(32, '0') if ($Contains) { if ($Contains -match "\A${IPv4Regex}\z") { return Test-IPIsInNetwork $Contains $o.BinaryNetworkAddress $o.BinaryNetworkAddress.SubString(0, $o.NetworkLength).PadRight(32, '1') } else { Write-Error "Get-IPAddressRangeInformation - Invalid IPv4 address specified with -Contains" return } } $o.NetworkAddress = Convert-BinaryToIP $o.BinaryNetworkAddress if ($o.NetworkLength -eq 32 -or $o.NetworkLength -eq 31) { $o.HostMin = $o.IP } else { $o.HostMin = Convert-BinaryToIP ([System.Convert]::ToString(([System.Convert]::ToInt64($o.BinaryNetworkAddress, 2) + 1), 2)).PadLeft(32, '0') } [string] $BinaryBroadcastIP = $o.BinaryNetworkAddress.SubString(0, $o.NetworkLength).PadRight(32, '1') $o.BinaryBroadcast = $BinaryBroadcastIP [int64] $DecimalHostMax = [System.Convert]::ToInt64($BinaryBroadcastIP, 2) - 1 [string] $BinaryHostMax = [System.Convert]::ToString($DecimalHostMax, 2).PadLeft(32, '0') $o.HostMax = Convert-BinaryToIP $BinaryHostMax $o.TotalHosts = [int64][System.Convert]::ToString(([System.Convert]::ToInt64($BinaryBroadcastIP, 2) - [System.Convert]::ToInt64($o.BinaryNetworkAddress, 2) + 1)) $o.UsableHosts = $o.TotalHosts - 2 if ($o.NetworkLength -eq 32) { $o.Broadcast = $Null $o.UsableHosts = [int64] 1 $o.TotalHosts = [int64] 1 $o.HostMax = $o.IP } elseif ($o.NetworkLength -eq 31) { $o.Broadcast = $Null $o.UsableHosts = [int64] 2 $o.TotalHosts = [int64] 2 [int64] $DecimalHostMax2 = [System.Convert]::ToInt64($BinaryBroadcastIP, 2) [string] $BinaryHostMax2 = [System.Convert]::ToString($DecimalHostMax2, 2).PadLeft(32, '0') $o.HostMax = Convert-BinaryToIP $BinaryHostMax2 } elseif ($o.NetworkLength -eq 30) { $o.UsableHosts = [int64] 2 $o.TotalHosts = [int64] 4 $o.Broadcast = Convert-BinaryToIP $BinaryBroadcastIP } else { $o.Broadcast = Convert-BinaryToIP $BinaryBroadcastIP } if ($Enumerate) { $IPRange = @(Get-IPRange $o.BinaryNetworkAddress $o.BinaryNetworkAddress.SubString(0, $o.NetworkLength).PadRight(32, '1')) if ((31, 32) -notcontains $o.NetworkLength ) { $IPRange = $IPRange[1..($IPRange.Count - 1)] $IPRange = $IPRange[0..($IPRange.Count - 2)] } $o.IPEnumerated = $IPRange } else { $o.IPEnumerated = @() } [PSCustomObject]$o } function Join-UriQuery { <# .SYNOPSIS Provides ability to join two Url paths together including advanced querying .DESCRIPTION Provides ability to join two Url paths together including advanced querying which is useful for RestAPI/GraphApi calls .PARAMETER BaseUri Primary Url to merge .PARAMETER RelativeOrAbsoluteUri Additional path to merge with primary url (optional) .PARAMETER QueryParameter Parameters and their values in form of hashtable .PARAMETER EscapeUriString If set, will escape the url string .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' -QueryParameter @{ page = 1 per_page = 20 search = 'SearchString' } .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz/wp-json/wp/v2/posts' -QueryParameter @{ page = 1 per_page = 20 search = 'SearchString' } .EXAMPLE Join-UriQuery -BaseUri 'https://evotec.xyz' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .NOTES General notes #> [alias('Join-UrlQuery')] [CmdletBinding()] param ( [parameter(Mandatory)][uri] $BaseUri, [parameter(Mandatory = $false)][uri] $RelativeOrAbsoluteUri, [Parameter()][System.Collections.IDictionary] $QueryParameter, [alias('EscapeUrlString')][switch] $EscapeUriString ) Begin { Add-Type -AssemblyName System.Web } Process { if ($BaseUri -and $RelativeOrAbsoluteUri) { $Url = Join-Uri -BaseUri $BaseUri -RelativeOrAbsoluteUri $RelativeOrAbsoluteUri } else { $Url = $BaseUri } if ($QueryParameter) { $Collection = [System.Web.HttpUtility]::ParseQueryString([String]::Empty) foreach ($key in $QueryParameter.Keys) { $Collection.Add($key, $QueryParameter.$key) } } $uriRequest = [System.UriBuilder] $Url if ($Collection) { $uriRequest.Query = $Collection.ToString() } if (-not $EscapeUriString) { $uriRequest.Uri.AbsoluteUri } else { [System.Uri]::EscapeUriString($uriRequest.Uri.AbsoluteUri) } } } function Remove-EmptyValue { [alias('Remove-EmptyValues')] [CmdletBinding()] param( [alias('Splat', 'IDictionary')][Parameter(Mandatory)][System.Collections.IDictionary] $Hashtable, [string[]] $ExcludeParameter, [switch] $Recursive, [int] $Rerun, [switch] $DoNotRemoveNull, [switch] $DoNotRemoveEmpty, [switch] $DoNotRemoveEmptyArray, [switch] $DoNotRemoveEmptyDictionary ) foreach ($Key in [string[]] $Hashtable.Keys) { if ($Key -notin $ExcludeParameter) { if ($Recursive) { if ($Hashtable[$Key] -is [System.Collections.IDictionary]) { if ($Hashtable[$Key].Count -eq 0) { if (-not $DoNotRemoveEmptyDictionary) { $Hashtable.Remove($Key) } } else { Remove-EmptyValue -Hashtable $Hashtable[$Key] -Recursive:$Recursive } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } else { if (-not $DoNotRemoveNull -and $null -eq $Hashtable[$Key]) { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmpty -and $Hashtable[$Key] -is [string] -and $Hashtable[$Key] -eq '') { $Hashtable.Remove($Key) } elseif (-not $DoNotRemoveEmptyArray -and $Hashtable[$Key] -is [System.Collections.IList] -and $Hashtable[$Key].Count -eq 0) { $Hashtable.Remove($Key) } } } } if ($Rerun) { for ($i = 0; $i -lt $Rerun; $i++) { Remove-EmptyValue -Hashtable $Hashtable -Recursive:$Recursive } } } function Select-Properties { <# .SYNOPSIS Allows for easy selecting property names from one or multiple objects .DESCRIPTION Allows for easy selecting property names from one or multiple objects. This is especially useful with using AllProperties parameter where we want to make sure to get all properties from all objects. .PARAMETER Objects One or more objects .PARAMETER Property Properties to include .PARAMETER ExcludeProperty Properties to exclude .PARAMETER AllProperties All unique properties from all objects .PARAMETER PropertyNameReplacement Default property name when object has no properties .EXAMPLE $Object1 = [PSCustomobject] @{ Name1 = '1' Name2 = '3' Name3 = '5' } $Object2 = [PSCustomobject] @{ Name4 = '2' Name5 = '6' Name6 = '7' } Select-Properties -Objects $Object1, $Object2 -AllProperties #OR: $Object1, $Object2 | Select-Properties -AllProperties -ExcludeProperty Name6 -Property Name3 .EXAMPLE $Object3 = [Ordered] @{ Name1 = '1' Name2 = '3' Name3 = '5' } $Object4 = [Ordered] @{ Name4 = '2' Name5 = '6' Name6 = '7' } Select-Properties -Objects $Object3, $Object4 -AllProperties $Object3, $Object4 | Select-Properties -AllProperties .NOTES General notes #> [CmdLetBinding()] param( [Array][Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] $Objects, [string[]] $Property, [string[]] $ExcludeProperty, [switch] $AllProperties, [string] $PropertyNameReplacement = '*' ) Begin { function Select-Unique { [CmdLetBinding()] param( [System.Collections.IList] $Object ) [Array] $CleanedList = foreach ($O in $Object) { if ($null -ne $O) { $O } } $New = $CleanedList.ToLower() | Select-Object -Unique $Selected = foreach ($_ in $New) { $Index = $Object.ToLower().IndexOf($_) if ($Index -ne -1) { $Object[$Index] } } $Selected } $ObjectsList = [System.Collections.Generic.List[Object]]::new() } Process { foreach ($Object in $Objects) { $ObjectsList.Add($Object) } } End { if ($ObjectsList.Count -eq 0) { Write-Warning 'Select-Properties - Unable to process. Objects count equals 0.' return } if ($ObjectsList[0] -is [System.Collections.IDictionary]) { if ($AllProperties) { [Array] $All = foreach ($_ in $ObjectsList) { $_.Keys } $FirstObjectProperties = Select-Unique -Object $All } else { $FirstObjectProperties = $ObjectsList[0].Keys } if ($Property.Count -gt 0 -and $ExcludeProperty.Count -gt 0) { $FirstObjectProperties = foreach ($_ in $FirstObjectProperties) { if ($Property -contains $_ -and $ExcludeProperty -notcontains $_) { $_ continue } } } elseif ($Property.Count -gt 0) { $FirstObjectProperties = foreach ($_ in $FirstObjectProperties) { if ($Property -contains $_) { $_ continue } } } elseif ($ExcludeProperty.Count -gt 0) { $FirstObjectProperties = foreach ($_ in $FirstObjectProperties) { if ($ExcludeProperty -notcontains $_) { $_ continue } } } } elseif ($ObjectsList[0].GetType().Name -match 'bool|byte|char|datetime|decimal|double|ExcelHyperLink|float|int|long|sbyte|short|string|timespan|uint|ulong|URI|ushort') { $FirstObjectProperties = $PropertyNameReplacement } else { if ($Property.Count -gt 0 -and $ExcludeProperty.Count -gt 0) { $ObjectsList = $ObjectsList | Select-Object -Property $Property -ExcludeProperty $ExcludeProperty } elseif ($Property.Count -gt 0) { $ObjectsList = $ObjectsList | Select-Object -Property $Property } elseif ($ExcludeProperty.Count -gt 0) { $ObjectsList = $ObjectsList | Select-Object -Property '*' -ExcludeProperty $ExcludeProperty } if ($AllProperties) { [Array] $All = foreach ($_ in $ObjectsList) { $ListProperties = $_.PSObject.Properties.Name if ($null -ne $ListProperties) { $ListProperties } } $FirstObjectProperties = Select-Unique -Object $All } else { $FirstObjectProperties = $ObjectsList[0].PSObject.Properties.Name } } $FirstObjectProperties } } function Convert-BinaryToIP { [cmdletBinding()] param( [string] $Binary ) $Binary = $Binary -replace '\s+' if ($Binary.Length % 8) { Write-Warning -Message "Convert-BinaryToIP - Binary string '$Binary' is not evenly divisible by 8." return $Null } [int] $NumberOfBytes = $Binary.Length / 8 $Bytes = @(foreach ($i in 0..($NumberOfBytes - 1)) { try { [System.Convert]::ToByte($Binary.Substring(($i * 8), 8), 2) } catch { Write-Warning -Message "Convert-BinaryToIP - Error converting '$Binary' to bytes. `$i was $i." return $Null } }) return $Bytes -join '.' } function Convert-IPToBinary { [cmdletBinding()] param( [string] $IP ) $IPv4Regex = '(?:(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)\.){3}(?:0?0?\d|0?[1-9]\d|1\d\d|2[0-5][0-5]|2[0-4]\d)' $IP = $IP.Trim() if ($IP -match "\A${IPv4Regex}\z") { try { return ($IP.Split('.') | ForEach-Object { [System.Convert]::ToString([byte] $_, 2).PadLeft(8, '0') }) -join '' } catch { Write-Warning -Message "Convert-IPToBinary - Error converting '$IP' to a binary string: $_" return $Null } } else { Write-Warning -Message "Convert-IPToBinary - Invalid IP detected: '$IP'. Conversion failed." return $Null } } function Get-IPRange { [cmdletBinding()] param( [string] $StartBinary, [string] $EndBinary ) [int64] $StartInt = [System.Convert]::ToInt64($StartBinary, 2) [int64] $EndInt = [System.Convert]::ToInt64($EndBinary, 2) for ($BinaryIP = $StartInt; $BinaryIP -le $EndInt; $BinaryIP++) { Convert-BinaryToIP ([System.Convert]::ToString($BinaryIP, 2).PadLeft(32, '0')) } } function Join-Uri { <# .SYNOPSIS Provides ability to join two Url paths together .DESCRIPTION Provides ability to join two Url paths together .PARAMETER BaseUri Primary Url to merge .PARAMETER RelativeOrAbsoluteUri Additional path to merge with primary url .EXAMPLE Join-Uri 'https://evotec.xyz/' '/wp-json/wp/v2/posts' .EXAMPLE Join-Uri 'https://evotec.xyz/' 'wp-json/wp/v2/posts' .EXAMPLE Join-Uri -BaseUri 'https://evotec.xyz/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .EXAMPLE Join-Uri -BaseUri 'https://evotec.xyz/test/' -RelativeOrAbsoluteUri '/wp-json/wp/v2/posts' .NOTES General notes #> [alias('Join-Url')] [cmdletBinding()] param( [parameter(Mandatory)][uri] $BaseUri, [parameter(Mandatory)][uri] $RelativeOrAbsoluteUri ) return ($BaseUri.OriginalString.TrimEnd('/') + "/" + $RelativeOrAbsoluteUri.OriginalString.TrimStart('/')) } function Test-IPIsInNetwork { [cmdletBinding()] param( [string] $IP, [string] $StartBinary, [string] $EndBinary ) $TestIPBinary = Convert-IPToBinary $IP [int64] $TestIPInt64 = [System.Convert]::ToInt64($TestIPBinary, 2) [int64] $StartInt64 = [System.Convert]::ToInt64($StartBinary, 2) [int64] $EndInt64 = [System.Convert]::ToInt64($EndBinary, 2) if ($TestIPInt64 -ge $StartInt64 -and $TestIPInt64 -le $EndInt64) { return $True } else { return $False } } function Get-FieldsFromSchema { [CmdletBinding()] param( [PSCustomobject] $Schema, [string] $SchemaObject ) if (-not $Script:InfobloxSchemaFields) { $Script:InfobloxSchemaFields = [ordered] @{} } if ($Script:InfobloxSchemaFields[$SchemaObject]) { $Script:InfobloxSchemaFields[$SchemaObject] } else { if (-not $Schema) { $Schema = Get-InfobloxSchema -Object $SchemaObject } if ($Schema -and $Schema.fields.name) { $FilteredFields = foreach ($Field in $Schema.fields) { if ($Field.supports -like "*r*") { $Field.Name } } $Script:InfobloxSchemaFields[$SchemaObject] = ($FilteredFields -join ',') $Script:InfobloxSchemaFields[$SchemaObject] } else { Write-Warning -Message "Get-FieldsFromSchema - Failed to fetch schema for record type 'allrecords'. Using defaults" } } } function Hide-SelfSignedCerts { [cmdletbinding()] param( ) try { Add-Type -TypeDefinition @" 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 = [TrustAllCertsPolicy]::new() } catch { Write-Warning -Message "Hide-SelfSignedCerts - Error when trying to hide self-signed certificates: $($_.Exception.Message)" } } function New-WebSession { [cmdletbinding()] param( [System.Collections.IDictionary]$Cookies, [Uri]$For ) $newSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new() foreach ($entry in $Cookies.GetEnumerator()) { $cookie = [System.Net.Cookie]::new($entry.Name, $entry.Value) if ($For) { $newSession.Cookies.Add([uri]::new($For, '/'), $cookie) } else { $newSession.Cookies.Add($cookie) } } $newSession } function Select-ObjectByProperty { [CmdletBinding()] param( [Parameter(Position = 0, ValueFromPipeline)][Array] $Object, [System.Collections.IDictionary] $AddObject, [alias('FirstProperty')][Parameter()][string[]] $FirstProperties, [alias('LastProperty')][Parameter()][string[]] $LastProperties, [string[]] $AllProperties ) process { foreach ($O in $Object) { # If we have an object, we can get the properties from it # we assume user can provide AllProperties instead of current object properties $Properties = if ($AllProperties) { $AllProperties } else { $O.PSObject.Properties.Name } $ReturnObject = [ordered] @{} foreach ($Property in $FirstProperties) { if ($Properties -contains $Property) { $ReturnObject[$Property] = $O.$Property } } if ($AddObject) { foreach ($Property in $AddObject.Keys) { $ReturnObject[$Property] = $AddObject[$Property] } } foreach ($Property in $Properties) { if ($Property -notin $LastProperties -and $Property -notin $FirstProperties) { $ReturnObject[$Property] = $O.$Property } } foreach ($Property in $LastProperties) { if ($Properties -contains $Property) { $ReturnObject[$Property] = $O.$Property } } [pscustomobject]$ReturnObject } } } function Add-InfoBloxDNSRecord { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Name Parameter description .PARAMETER IPAddress Parameter description .PARAMETER CanonicalName Parameter description .PARAMETER PtrName Parameter description .PARAMETER Type Parameter description .EXAMPLE Add-InfoBloxDNSRecord -Name 'Test' -IPv4Address '10.10.10.10' -Type 'A' .EXAMPLE Add-InfoBloxDNSRecord -Name 'Test' -IPv4Address '10.10.10.10' -Type 'HOST' .EXAMPLE Add-InfoBloxDNSRecord -Name 'Test' -CanonicalName 'test2.mcdonalds.com' -Type 'CNAME' .NOTES General notes #> [CmdletBinding(SupportsShouldProcess)] param( [string] $Name, [Alias('IPv4Address', 'IPv6Address')][string] $IPAddress, [string] $CanonicalName, [string] $PtrName, [string] $Text, [parameter(Mandatory)][ValidateSet( 'A', #'AAAA', 'CNAME', 'HOST', 'PTR' #'DName', #'DNSKEY', 'DS', 'Host', 'host_ipv4addr', 'host_ipv6addr', #'LBDN', 'MX', 'NAPTR', 'NS', 'NSEC', #'NSEC3', 'NSEC3PARAM', 'PTR', 'RRSIG', 'SRV', 'TXT' )] [string] $Type ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Add-InfoBloxDNSRecord - You must first connect to an Infoblox server using Connect-Infoblox' return } # Lets convert it to lowercase, since Infoblox is case sensitive $Type = $Type.ToLower() if ($Type -eq 'A') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with IPAddress: '$IPAddress'" if ($Name -and $IPAddress) { $Body = [ordered] @{ name = $Name.ToLower() ipv4addr = $IPAddress } } else { if ($ErrorActionPreference -eq 'Stop') { throw "Add-InfoBloxDNSRecord - 'Name' and 'IPAddress' are required for $Type record" } Write-Warning -Message "'Name' and 'IPAddress' are required for $Type record" return } } elseif ($Type -eq 'CNAME') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with IPAddress: '$IPAddress'" if ($Name -and $CanonicalName) { $Body = [ordered] @{ name = $Name.ToLower() canonical = $CanonicalName.ToLower() } } else { if ($ErrorActionPreference -eq 'Stop') { throw "'Name' and 'CanonicalName' are required for $Type record" } Write-Warning -Message "Add-InfoBloxDNSRecord - 'Name' and 'CanonicalName' are required for $Type record" return } } elseif ($Type -eq 'AAAA') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with IPAddress: '$IPAddress'" if ($Name -and $IPAddress) { $Body = [ordered] @{ name = $Name.ToLower() ipv6addr = $IPAddress } } else { if ($ErrorActionPreference -eq 'Stop') { throw "'Name' and 'IPAddress' are required for $Type record" } Write-Warning -Message "Add-InfoBloxDNSRecord - 'Name' and 'IPAddress' are required for $Type record" return } } elseif ($Type -eq 'HOST') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with IPAddress: '$IPAddress'" if ($Name -and $IPAddress) { $Body = [ordered] @{ name = $Name.ToLower() ipv4addrs = @( @{ ipv4addr = $IPAddress } ) } } else { if ($ErrorActionPreference -eq 'Stop') { throw "'Name' and 'IPAddress' are required for '$Type' record" } Write-Warning -Message "Add-InfoBloxDNSRecord - 'Name' and 'IPAddress' are required for '$Type' record" return } } elseif ($Type -eq 'PTR') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with IPAddress: '$IPAddress'" if ($Name -and $IPAddress -and $PtrName) { $Body = [ordered] @{ name = $Name.ToLower() ptrdname = $PtrName.ToLower() ipv4addr = $IPAddress } } else { if ($ErrorActionPreference -eq 'Stop') { throw "'Name' and 'IPAddress' and 'PtrName' are required for '$Type' record" } Write-Warning -Message "Add-InfoBloxDNSRecord - 'Name' and 'IPAddress' and 'PtrName' are required for '$Type' record" return } } elseif ($Type -eq 'TXT') { Write-Verbose -Message "Add-InfoBloxDNSRecord - Adding $Type record $Name with TEXT: '$Text'" if ($Name -and $IPAddress) { $Body = [ordered] @{ name = $Name.ToLower() text = $Text.ToLower() } } else { if ($ErrorActionPreference -eq 'Stop') { throw "'Name' and 'Text' are required for '$Type' record" } Write-Warning -Message "Add-InfoBloxDNSRecord - 'Name' and 'Text' are required for '$Type' record" return } } else { # won't trigger, but lets leave it like that if ($ErrorActionPreference -eq 'Stop') { throw "Add-InfoBloxDNSRecord - Type $Type not supported" } Write-Warning -Message "Add-InfoBloxDNSRecord - Type $Type not supported" return } $invokeInfobloxQuerySplat = @{ RelativeUri = "record:$Type" Method = 'POST' Body = $Body } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Add-InfoBloxDNSRecord - Added $Type / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Add-InfoBloxDNSRecord - Failed to add $Type, error: $varWarning" } } } function Add-InfobloxFixedAddress { <# .SYNOPSIS Add a fixed mac address to an IP address on an Infoblox server .DESCRIPTION Add a fixed mac address to an IP address on an Infoblox server A fixed address is a specific IP address that a DHCP server always assigns when a lease request comes from a particular MAC address of the client. For example, if you have a printer in your network, you can reserve a particular IP address to be assigned to it every time it is turned on. .PARAMETER IPv4Address IPv4 address to add the mac address to .PARAMETER MacAddress Mac address to add to the IPv4 address .EXAMPLE Add-InfobloxFixedAddress -IPv4Address '10.2.2.18' -MacAddress '00:50:56:9A:00:01' .NOTES General notes #> [cmdletbinding(SupportsShouldProcess)] param( [ValidateNotNullOrEmpty()][parameter(Mandatory)][string] $IPv4Address, [ValidatePattern("([a-zA-Z0-9]{2}:){5}[a-zA-Z0-9]{2}")][parameter(Mandatory)][string] $MacAddress ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Add-InfobloxFixedAddress - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Add-InfobloxFixedAddress - Adding IPv4Address $IPv4Address to MacAddress $MacAddress" $invokeInfobloxQuerySplat = @{ RelativeUri = 'fixedaddress' Method = 'POST' QueryParameter = @{ ipv4addr = $IPv4Address mac = $MacAddress.ToLower() } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Add-InfobloxFixedAddress - Added $($Mac.ipv4addr) with mac address $($Mac.mac) / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Add-InfobloxFixedAddress - Failed to add $($Mac.ipv4addr) with mac address $($Mac.mac), error: $varWarning" } } } function Connect-Infoblox { [CmdletBinding()] param( [Parameter(Mandatory, ParameterSetName = 'UserName')] [Parameter(Mandatory, ParameterSetName = 'Credential')] [string] $Server, [Parameter(Mandatory, ParameterSetName = 'UserName')][string] $Username, [alias('SecurePassword')][Parameter(Mandatory, ParameterSetName = 'UserName')][string] $EncryptedPassword, [Parameter(Mandatory, ParameterSetName = 'Credential')][pscredential] $Credential, [Parameter(ParameterSetName = 'UserName')] [Parameter(ParameterSetName = 'Credential')] [string] $ApiVersion = '1.0', [Parameter(ParameterSetName = 'UserName')] [Parameter(ParameterSetName = 'Credential')] [switch] $EnableTLS12, [Parameter(ParameterSetName = 'UserName')] [Parameter(ParameterSetName = 'Credential')] [switch] $AllowSelfSignedCerts ) if ($AllowSelfSignedCerts) { Hide-SelfSignedCerts } if ($EnableTLS12) { [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 } if ($Username -and $EncryptedPassword) { try { $Password = $SecurePassword | ConvertTo-SecureString -ErrorAction Stop $Credential = [pscredential]::new($Username, $Password) } catch { if ($ErrorActionPreference -eq 'Stop') { throw } Write-Warning -Message "Connect-Infoblox - Unable to convert password to secure string. Error: $($_.Exception.Message)" $Script:InfobloxConfiguration = $null return } } $PSDefaultParameterValues['Invoke-InfobloxQuery:Credential'] = $Credential $PSDefaultParameterValues['Invoke-InfobloxQuery:Server'] = $Server #$PSDefaultParameterValues['Invoke-InfobloxQuery:ApiVersion'] = $ApiVersion $PSDefaultParameterValues['Invoke-InfobloxQuery:BaseUri'] = "https://$Server/wapi/v$apiVersion" $Script:InfobloxConfiguration = [ordered] @{ ApiVersion = $ApiVersion Credential = $Credential Server = $Server BaseUri = "https://$Server/wapi/v$apiVersion" } } function Disconnect-Infoblox { <# .SYNOPSIS Disconnects from an InfoBlox server .DESCRIPTION Disconnects from an InfoBlox server As this is a REST API it doesn't really disconnect, but it does clear the script variable to clear the credentials from memory .EXAMPLE Disconnect-Infoblox .NOTES General notes #> [cmdletbinding()] param() $Script:InfobloxConfiguration = $null } function Get-InfobloxDHCPLease { [alias('Get-InfobloxDHCPLeases')] [CmdletBinding()] param( [string] $Network, [string] $IPv4Address, [string] $Hostname, [switch] $PartialMatch ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDHCPLease - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfobloxDHCPLease - Requesting DHCP leases for Network [$Network] / IPv4Address [$IPv4Address] / Hostname [$Hostname] / PartialMatch [$($PartialMatch.IsPresent)]" $invokeInfobloxQuerySplat = @{ RelativeUri = 'lease' Method = 'GET' QueryParameter = @{ _return_fields = 'binding_state,hardware,client_hostname,fingerprint,address,network_view' _max_results = 1000000 } } if ($Network) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."network~" = $Network.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.network = $Network.ToLower() } } if ($IPv4Address) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."ipv4addr~" = $IPv4Address.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.ipv4addr = $IPv4Address.ToLower() } } if ($Hostname) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."name~" = $Hostname.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.name = $Hostname.ToLower() } } Invoke-InfobloxQuery @invokeInfobloxQuerySplat } function Get-InfobloxDHCPRange { [CmdletBinding()] param( [string] $Network, [switch] $PartialMatch, [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDHCPRange - You must first connect to an Infoblox server using Connect-Infoblox' return } if ($Network) { Write-Verbose -Message "Get-InfobloxDHCPRange - Requesting DHCP ranges for Network [$Network] / PartialMatch [$($PartialMatch.IsPresent)]" } else { Write-Verbose -Message "Get-InfobloxDHCPRange - Requesting DHCP ranges for all networks" } if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "range" } else { $ReturnFields = $Null } $invokeInfobloxQuerySplat = @{ RelativeUri = 'range' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } if ($Network) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."network~" = $Network.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.network = $Network.ToLower() } } Invoke-InfobloxQuery @invokeInfobloxQuerySplat } function Get-InfobloxDiscoveryTask { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDiscoveryTask - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "discoverytask" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'discoverytask' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxDNSAuthZone { [alias('Get-InfobloxDNSAuthZones')] [cmdletbinding()] param( [string] $FQDN, [string] $View ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSAuthZones - You must first connect to an Infoblox server using Connect-Infoblox' return } $invokeInfobloxQuerySplat = @{ RelativeUri = 'zone_auth' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = @( 'address' 'allow_active_dir' 'allow_fixed_rrset_order' 'allow_gss_tsig_for_underscore_zone' 'allow_gss_tsig_zone_updates' 'allow_query' 'allow_transfer' 'allow_update' 'allow_update_forwarding' 'aws_rte53_zone_info' 'cloud_info' 'comment' 'copy_xfer_to_notify' 'create_underscore_zones' 'ddns_force_creation_timestamp_update' 'ddns_principal_group' 'ddns_principal_tracking' 'ddns_restrict_patterns' 'ddns_restrict_patterns_list' 'ddns_restrict_protected' 'ddns_restrict_secure' 'ddns_restrict_static' 'disable' 'disable_forwarding' 'display_domain' 'dns_fqdn' 'dns_integrity_enable' 'dns_integrity_frequency' 'dns_integrity_member' 'dns_integrity_verbose_logging' 'dns_soa_email' 'dnssec_key_params' 'dnssec_keys' 'dnssec_ksk_rollover_date' 'dnssec_zsk_rollover_date' 'effective_check_names_policy' 'effective_record_name_policy' 'extattrs' 'external_primaries' 'external_secondaries' 'fqdn' 'grid_primary' 'grid_primary_shared_with_ms_parent_delegation' 'grid_secondaries' 'is_dnssec_enabled' 'is_dnssec_signed' 'is_multimaster' 'last_queried' 'locked' 'locked_by' 'mask_prefix' 'member_soa_mnames' 'member_soa_serials' 'ms_ad_integrated' 'ms_allow_transfer' 'ms_allow_transfer_mode' 'ms_dc_ns_record_creation' 'ms_ddns_mode' 'ms_managed' 'ms_primaries' 'ms_read_only' 'ms_secondaries' 'ms_sync_disabled' 'ms_sync_master_name' 'network_associations' 'network_view' 'notify_delay' 'ns_group' 'parent' 'prefix' 'primary_type' 'record_name_policy' 'records_monitored' 'rr_not_queried_enabled_time' 'scavenging_settings' 'soa_default_ttl' 'soa_email' 'soa_expire' 'soa_negative_ttl' 'soa_refresh' 'soa_retry' 'soa_serial_number' 'srgs' 'update_forwarding' 'use_allow_active_dir' 'use_allow_query' 'use_allow_transfer' 'use_allow_update' 'use_allow_update_forwarding' 'use_check_names_policy' 'use_copy_xfer_to_notify' 'use_ddns_force_creation_timestamp_update' 'use_ddns_patterns_restriction' 'use_ddns_principal_security' 'use_ddns_restrict_protected' 'use_ddns_restrict_static' 'use_dnssec_key_params' 'use_external_primary' 'use_grid_zone_timer' 'use_import_from' 'use_notify_delay' 'use_record_name_policy' 'use_scavenging_settings' 'use_soa_email' 'using_srg_associations' 'view' 'zone_format' 'zone_not_queried_enabled_time' ) -join ',' } } if ($View) { $invokeInfobloxQuerySplat.QueryParameter.view = $View.ToLower() } if ($FQDN) { $invokeInfobloxQuerySplat.QueryParameter.fqdn = $FQDN.ToLower() } Invoke-InfobloxQuery @invokeInfobloxQuerySplat | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxDNSDelegatedZone { [cmdletbinding()] param( [string] $Name, [string] $View ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSDelgatedZone - You must first connect to an Infoblox server using Connect-Infoblox' return } $invokeInfobloxQuerySplat = @{ RelativeUri = 'zone_delegated' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = "address,comment,delegate_to,delegated_ttl,disable,display_domain,dns_fqdn,enable_rfc2317_exclusion,extattrs,fqdn,locked,locked_by,mask_prefix,ms_ad_integrated,ms_ddns_mode,ms_managed,ms_read_only,ms_sync_master_name,ns_group,parent,prefix,use_delegated_ttl,using_srg_associations,view,zone_format" } } if ($View) { $invokeInfobloxQuerySplat.QueryParameter.view = $View.ToLower() } if ($Name) { $invokeInfobloxQuerySplat.QueryParameter.fqdn = $Name.ToLower() } Invoke-InfobloxQuery @invokeInfobloxQuerySplat | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxDNSForwardZone { [cmdletbinding()] param( [string] $Name, [string] $View ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSForwardZone - You must first connect to an Infoblox server using Connect-Infoblox' return } $invokeInfobloxQuerySplat = @{ RelativeUri = 'zone_forward' Method = 'GET' QueryParameter = @{ _max_results = 1000000 } } if ($View) { $invokeInfobloxQuerySplat.QueryParameter.view = $View.ToLower() } if ($Name) { $invokeInfobloxQuerySplat.QueryParameter.fqdn = $Name.ToLower() } Invoke-InfobloxQuery @invokeInfobloxQuerySplat | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxDNSRecord { [alias('Get-InfobloxDNSRecords')] [cmdletbinding()] param( [string] $Name, [string] $Zone, [string] $View, [switch] $PartialMatch, [ValidateSet( 'A', 'AAAA', 'CName', 'DName', 'DNSKEY', 'DS', 'Host', 'host_ipv4addr', 'host_ipv6addr', 'LBDN', 'MX', 'NAPTR', 'NS', 'NSEC', 'NSEC3', 'NSEC3PARAM', 'PTR', 'RRSIG', 'SRV', 'TXT' )] [string] $Type = 'Host', [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSRecord - You must first connect to an Infoblox server using Connect-Infoblox' return } $invokeInfobloxQuerySplat = @{ RelativeUri = "record:$($Type.ToLower())" Method = 'GET' QueryParameter = @{ _max_results = 1000000 } } if ($Type -eq 'Host') { $invokeInfobloxQuerySplat.QueryParameter._return_fields = 'name,dns_name,aliases,dns_aliases,ipv4addrs,configure_for_dns,view' } elseif ($Type -eq 'PTR') { $invokeInfobloxQuerySplat.QueryParameter._return_fields = 'aws_rte53_record_info,cloud_info,comment,creation_time,creator,ddns_principal,ddns_protected,disable,discovered_data,dns_name,dns_ptrdname,extattrs,forbid_reclamation,ipv4addr,ipv6addr,last_queried,ms_ad_user_data,name,ptrdname,reclaimable,shared_record_group,ttl,use_ttl,view,zone' } elseif ($Type -eq 'A') { $invokeInfobloxQuerySplat.QueryParameter._return_fields = 'ipv4addr,name,view,zone,cloud_info,comment,creation_time,creator,ddns_principal,ddns_protected,disable,discovered_data,dns_name,last_queried,ms_ad_user_data,reclaimable,shared_record_group,ttl,use_ttl' } if ($FetchFromSchema) { $invokeInfobloxQuerySplat.QueryParameter._return_fields = Get-FieldsFromSchema -SchemaObject "record:$Type" } if ($Zone) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."zone~" = $Zone.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.zone = $Zone.ToLower() } } if ($View) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."view~" = $View.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.view = $View.ToLower() } } if ($Name) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."name~" = $Name.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.name = $Name.ToLower() } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat if ($Type -eq 'A') { $Output | Select-ObjectByProperty -LastProperty '_ref' -FirstProperty 'name', 'ipv4addr', 'view', 'zone', 'cloud_info', 'comment', 'creation_time', 'creator', 'ddns_principal', 'ddns_protected', 'disable', 'discovered_data', 'dns_name', 'last_queried', 'ms_ad_user_data', 'reclaimable', 'shared_record_group', 'ttl', 'use_ttl' } elseif ($Type -eq 'HOST') { $Output | Select-ObjectByProperty -LastProperty '_ref' -FirstProperty 'name', 'dns_name', 'aliases', 'dns_aliases', 'view', 'configure_for_dns', 'configure_for_dhcp', 'host', 'ipv4addr', 'ipv4addr_ref' } else { $Output | Select-ObjectByProperty -LastProperty '_ref' } } function Get-InfobloxDNSRecordAll { [alias('Get-InfobloxDNSRecordsAll')] [cmdletbinding()] param( [string] $Name, [string] $Zone, [string] $View, [switch] $PartialMatch, [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSRecordAll - You must first connect to an Infoblox server using Connect-Infoblox' return } $invokeInfobloxQuerySplat = @{ RelativeUri = "allrecords" Method = 'GET' QueryParameter = @{ _max_results = 1000000 } } $invokeInfobloxQuerySplat.QueryParameter._return_fields = 'address,comment,creator,ddns_principal,ddns_protected,disable,dtc_obscured,name,reclaimable,record,ttl,type,view,zone' if ($FetchFromSchema) { <# if (-not $Script:InfobloxSchemaFields) { $Script:InfobloxSchemaFields = [ordered] @{} } if ($Script:InfobloxSchemaFields["allrecords"]) { $invokeInfobloxQuerySplat.QueryParameter._return_fields = ($Script:InfobloxSchemaFields["allrecords"]) } else { $Schema = Get-InfobloxSchema -Object "allrecords" if ($Schema -and $Schema.fields.name) { $invokeInfobloxQuerySplat.QueryParameter._return_fields = ($Schema.fields.Name -join ',') $Script:InfobloxSchemaFields["allrecords"] = ($Schema.fields.Name -join ',') } else { Write-Warning -Message "Get-InfobloxDNSRecordAll - Failed to fetch schema for record type 'allrecords'. Using defaults" } } #> $invokeInfobloxQuerySplat.QueryParameter._return_fields = Get-FieldsFromSchema -SchemaObject "allrecords" } if ($Zone) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."zone~" = $Zone.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.zone = $Zone.ToLower() } } if ($View) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."view~" = $View.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.view = $View.ToLower() } } if ($Name) { if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."name~" = $Name.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.name = $Name.ToLower() } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $AllProperties = Select-Properties -AllProperties -Object $Output $Output | Select-ObjectByProperty -LastProperty '_ref' -FirstProperty 'zone', 'type', 'name', 'address', 'disable', 'creator' -AllProperties $AllProperties } function Get-InfobloxDNSView { [cmdletbinding()] param( ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxDNSView - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfobloxDNSView - Requesting DNS View" $invokeInfobloxQuerySplat = @{ RelativeUri = 'view' Method = 'GET' QueryParameter = @{ _max_results = 1000000 # _return_fields = 'mac,ipv4addr,network_view' } } Invoke-InfobloxQuery @invokeInfobloxQuerySplat } function Get-InfobloxFixedAddress { [cmdletbinding()] param( [parameter(Mandatory)][string] $MacAddress, [switch] $PartialMatch ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxFixedAddress - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfobloxFixedAddress - Requesting MacAddress [$MacAddress] / PartialMatch [$($PartialMatch.IsPresent)]" $invokeInfobloxQuerySplat = @{ RelativeUri = 'fixedaddress' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = 'mac,ipv4addr,network_view' } } if ($PartialMatch) { $invokeInfobloxQuerySplat.QueryParameter."mac~" = $MacAddress.ToLower() } else { $invokeInfobloxQuerySplat.QueryParameter.mac = $MacAddress.ToLower() } Invoke-InfobloxQuery @invokeInfobloxQuerySplat } function Get-InfobloxGrid { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxGrid - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields $ReturnFields = 'allow_recursive_deletion,audit_log_format,audit_to_syslog_enable,automated_traffic_capture_setting,consent_banner_setting,csp_api_config,csp_grid_setting,deny_mgm_snapshots,descendants_action,dns_resolver_setting,dscp,email_setting,enable_gui_api_for_lan_vip,enable_lom,enable_member_redirect,enable_recycle_bin,enable_rir_swip,external_syslog_backup_servers,external_syslog_server_enable,http_proxy_server_setting,informational_banner_setting,is_grid_visualization_visible,lockout_setting,lom_users,mgm_strict_delegate_mode,ms_setting,name,nat_groups,ntp_setting,objects_changes_tracking_setting,password_setting,restart_banner_setting,restart_status,rpz_hit_rate_interval,rpz_hit_rate_max_query,rpz_hit_rate_min_query,scheduled_backup,security_banner_setting,security_setting,service_status,snmp_setting,support_bundle_download_timeout,syslog_facility,syslog_servers,syslog_size,threshold_traps,time_zone,token_usage_delay,traffic_capture_auth_dns_setting,traffic_capture_chr_setting,traffic_capture_qps_setting,traffic_capture_rec_dns_setting,traffic_capture_rec_queries_setting,trap_notifications,updates_download_member_config,vpn_port' if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "grid" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'grid' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxIPAddress { <# .SYNOPSIS Get Infoblox IP Address information for given network or IP address .DESCRIPTION Get Infoblox IP Address information for given network or IP address .PARAMETER Network Find IP address information for a specific network .PARAMETER IPv4Address Find IP address information for a specific IP address .PARAMETER Status Get IP addresses with a specific status, either Used or Unused .PARAMETER Name Get IP addresses with a specific name .PARAMETER Count Limit the number of results returned .EXAMPLE Get-InfobloxIPAddress -Network '10.2.2.0/24' .EXAMPLE Get-InfobloxIPAddress -Network '10.2.2.0/24' -Status Used -Verbose | Format-Table .EXAMPLE Get-InfobloxIPAddress -Network '10.2.2.0' -Verbose | Format-Table .NOTES General notes #> [cmdletbinding()] param( [parameter(ParameterSetName = 'Network')][string] $Network, [parameter(ParameterSetName = 'IPv4')][string] $IPv4Address, [parameter(ParameterSetName = 'Network')] [parameter(ParameterSetName = 'IPv4')] [parameter()][ValidateSet('Used', 'Unused')][string] $Status, [parameter(ParameterSetName = 'Network')] [parameter(ParameterSetName = 'IPv4')] [parameter()][string] $Name, [parameter(ParameterSetName = 'Network')] [parameter(ParameterSetName = 'IPv4')] [alias('Quantity')][parameter()][int] $Count ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxIPAddress - You must first connect to an Infoblox server using Connect-Infoblox' return } if ($Network) { Write-Verbose -Message "Get-InfobloxIPAddress - Requesting Network [$Network] Status [$Status]" } else { Write-Verbose -Message "Get-InfobloxIPAddress - Requesting IPv4Address [$IPv4Address] Status [$Status]" } $invokeInfobloxQuerySplat = [ordered]@{ RelativeUri = 'ipv4address' Method = 'GET' QueryParameter = [ordered]@{ _max_results = 1000000 } } if ($Network) { $invokeInfobloxQuerySplat.QueryParameter.network = $Network } if ($Status) { $invokeInfobloxQuerySplat.QueryParameter.status = $Status.ToUpper() } if ($Name) { $invokeInfobloxQuerySplat.QueryParameter.names = $Name } if ($IPv4Address) { $invokeInfobloxQuerySplat.QueryParameter.ip_address = $IPv4Address } if ($Count) { Invoke-InfobloxQuery @invokeInfobloxQuerySplat | Select-Object -First $Count | Select-ObjectByProperty -LastProperty '_ref' } else { Invoke-InfobloxQuery @invokeInfobloxQuerySplat | Select-ObjectByProperty -LastProperty '_ref' } } function Get-InfobloxMember { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxMember - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields $ReturnFields = 'config_addr_type,host_name,platform,service_type_configuration,vip_setting,node_info,service_status' if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "member" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'member' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -FirstProperty 'host_name' -LastProperty '_ref' } function Get-InfobloxNetwork { [OutputType([system.object[]])] [cmdletbinding()] param( [string] $Network, [string[]]$Properties, [switch] $Partial, [switch] $All ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxNetwork - You must first connect to an Infoblox server using Connect-Infoblox' return } $QueryParameter = [ordered]@{ _max_results = 1000000 _return_fields = @( "authority", "bootfile", "bootserver", "cloud_info", "comment", "conflict_count", "ddns_domainname", "ddns_generate_hostname", "ddns_server_always_updates", "ddns_ttl", "ddns_update_fixed_addresses", "ddns_use_option81", "deny_bootp", "dhcp_utilization", "dhcp_utilization_status", "disable", "discover_now_status", "discovered_bgp_as", "discovered_bridge_domain", "discovered_tenant", "discovered_vlan_id", "discovered_vlan_name", "discovered_vrf_description", "discovered_vrf_name", "discovered_vrf_rd", "discovery_basic_poll_settings", "discovery_blackout_setting", "discovery_engine_type", "discovery_member", "dynamic_hosts", "email_list", "enable_ddns", "enable_dhcp_thresholds", "enable_discovery", "enable_email_warnings", "enable_ifmap_publishing", "enable_pxe_lease_time", "enable_snmp_warnings", "endpoint_sources", "extattrs", "high_water_mark", "high_water_mark_reset", "ignore_dhcp_option_list_request", "ignore_id", "ignore_mac_addresses", "ipam_email_addresses", "ipam_threshold_settings", "ipam_trap_settings", "ipv4addr", "last_rir_registration_update_sent", "last_rir_registration_update_status", "lease_scavenge_time", "logic_filter_rules", "low_water_mark", "low_water_mark_reset", "members", "mgm_private", "mgm_private_overridable", "ms_ad_user_data", "netmask", "network", "network_container", "network_view", "nextserver", "options", "port_control_blackout_setting", "pxe_lease_time", "recycle_leases", "rir", "rir_organization", "rir_registration_status", "same_port_control_discovery_blackout", "static_hosts", "subscribe_settings", "total_hosts", "unmanaged", "unmanaged_count", "update_dns_on_lease_renewal", "use_authority", "use_blackout_setting", "use_bootfile", "use_bootserver", "use_ddns_domainname", "use_ddns_generate_hostname", "use_ddns_ttl", "use_ddns_update_fixed_addresses", "use_ddns_use_option81", "use_deny_bootp", "use_discovery_basic_polling_settings", "use_email_list", "use_enable_ddns", "use_enable_dhcp_thresholds", "use_enable_discovery", "use_enable_ifmap_publishing", "use_ignore_dhcp_option_list_request", "use_ignore_id", "use_ipam_email_addresses", "use_ipam_threshold_settings", "use_ipam_trap_settings", "use_lease_scavenge_time", "use_logic_filter_rules", "use_mgm_private", "use_nextserver", "use_options", "use_pxe_lease_time", "use_recycle_leases", "use_subscribe_settings", "use_update_dns_on_lease_renewal", "use_zone_associations", "utilization", "utilization_update", "vlans", "zone_associations" ) -join ',' } if ($All) { $ListNetworks = Invoke-InfobloxQuery -RelativeUri "network" -Method Get -QueryParameter $QueryParameter } elseif ($Network -and $Partial.IsPresent) { $QueryParameter."network~" = $Network } elseif ($Network) { $QueryParameter.network = $Network } else { return } $ListNetworks = Invoke-InfobloxQuery -RelativeUri "network" -Method Get -QueryParameter $QueryParameter #$ExtraProperties = $false foreach ($FoundNetwork in $ListNetworks) { $FullInformation = Get-IPAddressRangeInformation -Network $FoundNetwork.network <# $FoundNetwork.options name : dhcp-lease-time num : 51 use_option : False value : 43200 vendor_class : DHCP #> $OutputData = [ordered] @{ Network = $FoundNetwork.network NetworkRef = $FoundNetwork._ref IP = $FullInformation.IP # : 10.2.10.0 NetworkLength = $FullInformation.NetworkLength # : 24 SubnetMask = $FullInformation.SubnetMask # : 255.255.255.0 NetworkAddress = $FullInformation.NetworkAddress # : 10.2.10.0 HostMin = $FullInformation.HostMin # : 10.2.10.1 HostMax = $FullInformation.HostMax # : 10.2.10.254 TotalHosts = $FullInformation.TotalHosts # : 256 UsableHosts = $FullInformation.UsableHosts # : 254 Broadcast = $FullInformation.Broadcast # : 10.2.10.255 authority = $FoundNetwork.authority #: False cloud_info = $FoundNetwork.cloud_info #: @{authority_type=GM; delegated_scope=NONE; mgmt_platform=; owned_by_adaptor=False} comment = $FoundNetwork.comment #: found in CMDB conflict_count = $FoundNetwork.conflict_count #: 0 ddns_generate_hostname = $FoundNetwork.ddns_generate_hostname #: False ddns_server_always_updates = $FoundNetwork.ddns_server_always_updates #: True ddns_ttl = $FoundNetwork.ddns_ttl #: 0 ddns_update_fixed_addresses = $FoundNetwork.ddns_update_fixed_addresses #: False ddns_use_option81 = $FoundNetwork.ddns_use_option81 #: False deny_bootp = $FoundNetwork.deny_bootp #: False dhcp_utilization = $FoundNetwork.dhcp_utilization #: 0 dhcp_utilization_status = $FoundNetwork.dhcp_utilization_status #: LOW disable = $FoundNetwork.disable #: False discover_now_status = $FoundNetwork.discover_now_status #: NONE discovered_bgp_as = $FoundNetwork.discovered_bgp_as #: discovered_bridge_domain = $FoundNetwork.discovered_bridge_domain #: discovered_tenant = $FoundNetwork.discovered_tenant #: discovered_vlan_id = $FoundNetwork.discovered_vlan_id #: discovered_vlan_name = $FoundNetwork.discovered_vlan_name #: discovered_vrf_description = $FoundNetwork.discovered_vrf_description #: discovered_vrf_name = $FoundNetwork.discovered_vrf_name #: discovered_vrf_rd = $FoundNetwork.discovered_vrf_rd #: discovery_basic_poll_settings = $FoundNetwork.discovery_basic_poll_settings #: @{auto_arp_refresh_before_switch_port_polling=True; cli_collection=True; complete_ping_sweep=False; # = $FoundNetwork. # credential_group=default; device_profile=False; netbios_scanning=False; port_scanning=False; # = $FoundNetwork. # smart_subnet_ping_sweep=False; snmp_collection=True; switch_port_data_collection_polling=PERIODIC; # = $FoundNetwork. # switch_port_data_collection_polling_interval=3600} discovery_blackout_setting = $FoundNetwork.discovery_blackout_setting #: @{enable_blackout=False} discovery_engine_type = $FoundNetwork.discovery_engine_type #: NONE dynamic_hosts = $FoundNetwork.dynamic_hosts #: 0 email_list = $FoundNetwork.email_list #: {} enable_ddns = $FoundNetwork.enable_ddns #: False enable_dhcp_thresholds = $FoundNetwork.enable_dhcp_thresholds #: False enable_discovery = $FoundNetwork.enable_discovery #: False enable_email_warnings = $FoundNetwork.enable_email_warnings #: False enable_ifmap_publishing = $FoundNetwork.enable_ifmap_publishing #: False enable_pxe_lease_time = $FoundNetwork.enable_pxe_lease_time #: False enable_snmp_warnings = $FoundNetwork.enable_snmp_warnings #: False #extattrs = $FoundNetwork.extattrs #: @{Country=; Name=; Region=} high_water_mark = $FoundNetwork.high_water_mark #: 95 high_water_mark_reset = $FoundNetwork.high_water_mark_reset #: 85 ignore_dhcp_option_list_request = $FoundNetwork.ignore_dhcp_option_list_request #: False ignore_id = $FoundNetwork.ignore_id #: NONE ignore_mac_addresses = $FoundNetwork.ignore_mac_addresses #: {} ipam_email_addresses = $FoundNetwork.ipam_email_addresses #: {} ipam_threshold_settings = $FoundNetwork.ipam_threshold_settings #: @{reset_value=85; trigger_value=95} ipam_trap_settings = $FoundNetwork.ipam_trap_settings #: @{enable_email_warnings=False; enable_snmp_warnings=True} ipv4addr = $FoundNetwork.ipv4addr #: 172.23.0.0 lease_scavenge_time = $FoundNetwork.lease_scavenge_time #: -1 logic_filter_rules = $FoundNetwork.logic_filter_rules #: {} low_water_mark = $FoundNetwork.low_water_mark #: 0 low_water_mark_reset = $FoundNetwork.low_water_mark_reset #: 10 members = $FoundNetwork.members #: {} mgm_private = $FoundNetwork.mgm_private #: False mgm_private_overridable = $FoundNetwork.mgm_private_overridable #: True netmask = $FoundNetwork.netmask #: 27 network_container = $FoundNetwork.network_container #: 172.23.0.0/16 network_view = $FoundNetwork.network_view #: default options = $FoundNetwork.options #: {@{name=dhcp-lease-time; num=51; use_option=False; value=43200; vendor_class=DHCP}} port_control_blackout_setting = $FoundNetwork.port_control_blackout_setting #: @{enable_blackout=False} recycle_leases = $FoundNetwork.recycle_leases #: True rir = $FoundNetwork.rir #: NONE rir_registration_status = $FoundNetwork.rir_registration_status #: NOT_REGISTERED same_port_control_discovery_blackout = $FoundNetwork.same_port_control_discovery_blackout #: False static_hosts = $FoundNetwork.static_hosts #: 0 subscribe_settings = $FoundNetwork.subscribe_settings #: total_hosts = $FoundNetwork.total_hosts #: 0 unmanaged = $FoundNetwork.unmanaged #: False unmanaged_count = $FoundNetwork.unmanaged_count #: 0 update_dns_on_lease_renewal = $FoundNetwork.update_dns_on_lease_renewal #: False use_authority = $FoundNetwork.use_authority #: False use_blackout_setting = $FoundNetwork.use_blackout_setting #: False use_bootfile = $FoundNetwork.use_bootfile #: False use_bootserver = $FoundNetwork.use_bootserver #: False use_ddns_domainname = $FoundNetwork.use_ddns_domainname #: False use_ddns_generate_hostname = $FoundNetwork.use_ddns_generate_hostname #: False use_ddns_ttl = $FoundNetwork.use_ddns_ttl #: False use_ddns_update_fixed_addresses = $FoundNetwork.use_ddns_update_fixed_addresses #: False use_ddns_use_option81 = $FoundNetwork.use_ddns_use_option81 #: False use_deny_bootp = $FoundNetwork.use_deny_bootp #: False use_discovery_basic_polling_settings = $FoundNetwork.use_discovery_basic_polling_settings #: False use_email_list = $FoundNetwork.use_email_list #: False use_enable_ddns = $FoundNetwork.use_enable_ddns #: False use_enable_dhcp_thresholds = $FoundNetwork.use_enable_dhcp_thresholds #: False use_enable_discovery = $FoundNetwork.use_enable_discovery #: False use_enable_ifmap_publishing = $FoundNetwork.use_enable_ifmap_publishing #: False use_ignore_dhcp_option_list_request = $FoundNetwork.use_ignore_dhcp_option_list_request #: False use_ignore_id = $FoundNetwork.use_ignore_id #: False use_ipam_email_addresses = $FoundNetwork.use_ipam_email_addresses #: False use_ipam_threshold_settings = $FoundNetwork.use_ipam_threshold_settings #: False use_ipam_trap_settings = $FoundNetwork.use_ipam_trap_settings #: False use_lease_scavenge_time = $FoundNetwork.use_lease_scavenge_time #: False use_logic_filter_rules = $FoundNetwork.use_logic_filter_rules #: False use_mgm_private = $FoundNetwork.use_mgm_private #: False use_nextserver = $FoundNetwork.use_nextserver #: False use_options = $FoundNetwork.use_options #: False use_pxe_lease_time = $FoundNetwork.use_pxe_lease_time #: False use_recycle_leases = $FoundNetwork.use_recycle_leases #: False use_subscribe_settings = $FoundNetwork.use_subscribe_settings #: False use_update_dns_on_lease_renewal = $FoundNetwork.use_update_dns_on_lease_renewal #: False use_zone_associations = $FoundNetwork.use_zone_associations #: False utilization = $FoundNetwork.utilization #: 0 utilization_update = $FoundNetwork.utilization_update #: 1707318915 vlans = $FoundNetwork.vlans #: {} zone_associations = $FoundNetwork.zone_associations #: {} _ref = $FoundNetwork._ref #: network/ZG } foreach ($Extra in $FoundNetwork.extattrs.psobject.properties) { $OutputData[$Extra.Name] = $Extra.Value.value } [PSCustomObject]$OutputData } } function Get-InfobloxNetworkNextAvailableIP { [cmdletbinding(DefaultParameterSetName = 'Network')] param( [Parameter(Mandatory, ParameterSetName = 'Network')][string] $Network, [Parameter(Mandatory, ParameterSetName = 'NetworkRef')][string] $NetworkRef, [alias('Count')][int] $Quantity = 1 ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxNetworkNextAvailableIP - You must first connect to an Infoblox server using Connect-Infoblox' return } if ($Network) { $NetworkInformation = Get-InfobloxNetwork -Network $Network if ($NetworkInformation) { $NetworkRef = $NetworkInformation.NetworkRef } else { Write-Warning -Message "Get-InfobloxNetworkNextAvailableIP - No network found for [$Network]" return } } $invokeInfobloxQuerySplat = @{ RelativeUri = $NetworkRef QueryParameter = @{ _function = 'next_available_ip' num = $Quantity } Method = 'POST' } $Query = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Query) { $Query.ips } else { Write-Warning -Message "Get-InfobloxNetworkNextAvailableIP - No IP returned for network [$NetworkRef], error: $varWarning" } } function Get-InfobloxNetworkView { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxNetworkView - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfobloxNetworkView - Requesting Network View" if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "networkview" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'networkview' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxObjects { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateSet( "ad_auth_service", "admingroup", "adminrole", "adminuser", "allendpoints", "allnsgroup", "allrecords", "allrpzrecords", "approvalworkflow", "authpolicy", "awsrte53taskgroup", "awsuser", "bfdtemplate", "bulkhost", "bulkhostnametemplate", "cacertificate", "capacityreport", "captiveportal", "certificate:authservice", "csvimporttask", "db_objects", "dbsnapshot", "ddns:principalcluster", "ddns:principalcluster:group", "deleted_objects", "dhcp:statistics", "dhcpfailover", "dhcpoptiondefinition", "dhcpoptionspace", "discovery", "discovery:credentialgroup", "discovery:device", "discovery:devicecomponent", "discovery:deviceinterface", "discovery:deviceneighbor", "discovery:devicesupportbundle", "discovery:diagnostictask", "discovery:gridproperties", "discovery:memberproperties", "discovery:sdnnetwork", "discovery:status", "discovery:vrf", "discoverytask", "distributionschedule", "dns64group", "dtc", "dtc:allrecords", "dtc:certificate", "dtc:lbdn", "dtc:monitor", "dtc:monitor:http", "dtc:monitor:icmp", "dtc:monitor:pdp", "dtc:monitor:sip", "dtc:monitor:snmp", "dtc:monitor:tcp", "dtc:object", "dtc:pool", "dtc:record:a", "dtc:record:aaaa", "dtc:record:cname", "dtc:record:naptr", "dtc:record:srv", "dtc:server", "dtc:topology", "dtc:topology:label", "dtc:topology:rule", "dxl:endpoint", "extensibleattributedef", "fileop", "filterfingerprint", "filtermac", "filternac", "filteroption", "filterrelayagent", "fingerprint", "fixedaddress", "fixedaddresstemplate", "ftpuser", "grid", "grid:cloudapi", "grid:cloudapi:cloudstatistics", "grid:cloudapi:tenant", "grid:cloudapi:vm", "grid:cloudapi:vmaddress", "grid:dashboard", "grid:dhcpproperties", "grid:dns", "grid:filedistribution", "grid:license_pool", "grid:license_pool_container", "grid:maxminddbinfo", "grid:member:cloudapi", "grid:servicerestart:group", "grid:servicerestart:group:order", "grid:servicerestart:request", "grid:servicerestart:request:changedobject", "grid:servicerestart:status", "grid:threatanalytics", "grid:threatprotection", "grid:x509certificate", "hostnamerewritepolicy", "hsm:allgroups", "hsm:safenetgroup", "hsm:thalesgroup", "ipam:statistics", "ipv4address", "ipv6address", "ipv6dhcpoptiondefinition", "ipv6dhcpoptionspace", "ipv6fixedaddress", "ipv6fixedaddresstemplate", "ipv6network", "ipv6networkcontainer", "ipv6networktemplate", "ipv6range", "ipv6rangetemplate", "ipv6sharednetwork", "kerberoskey", "ldap_auth_service", "lease", "license:gridwide", "localuser:authservice", "macfilteraddress", "mastergrid", "member", "member:dhcpproperties", "member:dns", "member:filedistribution", "member:license", "member:parentalcontrol", "member:threatanalytics", "member:threatprotection", "memberdfp", "msserver", "msserver:adsites:domain", "msserver:adsites:site", "msserver:dhcp", "msserver:dns", "mssuperscope", "namedacl", "natgroup", "network", "network_discovery", "networkcontainer", "networktemplate", "networkuser", "networkview", "notification:rest:endpoint", "notification:rest:template", "notification:rule", "nsgroup", "nsgroup:delegation", "nsgroup:forwardingmember", "nsgroup:forwardstubserver", "nsgroup:stubmember", "orderedranges", "orderedresponsepolicyzones", "outbound:cloudclient", "parentalcontrol:avp", "parentalcontrol:blockingpolicy", "parentalcontrol:subscriber", "parentalcontrol:subscriberrecord", "parentalcontrol:subscribersite", "permission", "pxgrid:endpoint", "radius:authservice", "range", "rangetemplate", "record:a", "record:aaaa", "record:alias", "record:caa", "record:cname", "record:dhcid", "record:dname", "record:dnskey", "record:ds", "record:dtclbdn", "record:host", "record:host_ipv4addr", "record:host_ipv6addr", "record:mx", "record:naptr", "record:ns", "record:nsec", "record:nsec3", "record:nsec3param", "record:ptr", "record:rpz:a", "record:rpz:a:ipaddress", "record:rpz:aaaa", "record:rpz:aaaa:ipaddress", "record:rpz:cname", "record:rpz:cname:clientipaddress", "record:rpz:cname:clientipaddressdn", "record:rpz:cname:ipaddress", "record:rpz:cname:ipaddressdn", "record:rpz:mx", "record:rpz:naptr", "record:rpz:ptr", "record:rpz:srv", "record:rpz:txt", "record:rrsig", "record:srv", "record:tlsa", "record:txt", "record:unknown", "recordnamepolicy", "request", "restartservicestatus", "rir", "rir:organization", "roaminghost", "ruleset", "saml:authservice", "scavengingtask", "scheduledtask", "search", "sharednetwork", "sharedrecord:a", "sharedrecord:aaaa", "sharedrecord:cname", "sharedrecord:mx", "sharedrecord:srv", "sharedrecord:txt", "sharedrecordgroup", "smartfolder:children", "smartfolder:global", "smartfolder:personal", "snmpuser", "superhost", "superhostchild", "syslog:endpoint", "tacacsplus:authservice", "taxii", "tftpfiledir", "threatanalytics:analytics_whitelist", "threatanalytics:moduleset", "threatanalytics:whitelist", "threatinsight:cloudclient", "threatprotection:grid:rule", "threatprotection:profile", "threatprotection:profile:rule", "threatprotection:rule", "threatprotection:rulecategory", "threatprotection:ruleset", "threatprotection:ruletemplate", "threatprotection:statistics", "upgradegroup", "upgradeschedule", "upgradestatus", "userprofile", "vdiscoverytask", "view", "vlan", "vlanrange", "vlanview", "zone_auth", "zone_auth_discrepancy", "zone_delegated", "zone_forward", "zone_rp", "zone_stub" )][string] $Object, [int] $MaxResults, [switch] $FetchFromSchema, [string[]] $ReturnFields ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxObjects - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfobloxObjects - Requesting $Object" if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "$Object" } $invokeInfobloxQuerySplat = @{ RelativeUri = $Object.ToLower() Method = 'GET' QueryParameter = @{ _return_fields = $ReturnFields } } if ($MaxResults) { $invokeInfobloxQuerySplat.QueryParameter._max_results = $MaxResults } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxPermission { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxPermissions - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "permission" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'permission' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxResponsePolicyZones { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxResponsePolicyZones - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "zone_rp" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'zone_rp' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Get-InfobloxSchema { <# .SYNOPSIS Get the schema for Infoblox as a whole or a specific object .DESCRIPTION Get the schema for Infoblox as a whole or a specific object .PARAMETER Object The object to get the schema for .EXAMPLE Get-InfobloxSchema .EXAMPLE Get-InfobloxSchema -Object 'record:host' .NOTES General notes #> [CmdletBinding()] param( [string] $Object, [switch] $ReturnReadOnlyFields ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxSchema - You must first connect to an Infoblox server using Connect-Infoblox' return } if ($Object) { $invokeInfobloxQuerySplat = @{ RelativeUri = "$($Object.ToLower())" Method = 'Get' Query = @{ _schema = $true } } } else { $invokeInfobloxQuerySplat = @{ RelativeUri = "?_schema" Method = 'Get' } } $Query = Invoke-InfobloxQuery @invokeInfobloxQuerySplat if ($Query) { if ($ReturnReadOnlyFields) { Get-FieldsFromSchema -Schema $Query -SchemaObject $Object } else { $Query } } else { Write-Warning -Message 'Get-InfobloxSchema - No schema returned' } } function Get-InfoBloxSearch { [CmdletBinding()] param( [parameter(ParameterSetName = 'IPv4')][string] $IPv4Address ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfoBloxSearch - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Get-InfoBloxSearch - Requesting IPv4Address [$IPv4Address]" $invokeInfobloxQuerySplat = [ordered]@{ RelativeUri = 'search' Method = 'GET' QueryParameter = [ordered]@{ _max_results = 1000000 } } if ($IPv4Address) { $invokeInfobloxQuerySplat.QueryParameter.address = $IPv4Address } Invoke-InfobloxQuery @invokeInfobloxQuerySplat } function Get-InfobloxVDiscoveryTask { [cmdletbinding()] param( [switch] $FetchFromSchema ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Get-InfobloxVDiscoveryTask - You must first connect to an Infoblox server using Connect-Infoblox' return } # defalt return fields if ($FetchFromSchema) { $ReturnFields = Get-FieldsFromSchema -SchemaObject "vdiscoverytask" } $invokeInfobloxQuerySplat = @{ RelativeUri = 'vdiscoverytask' Method = 'GET' QueryParameter = @{ _max_results = 1000000 _return_fields = $ReturnFields } } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat $Output | Select-ObjectByProperty -LastProperty '_ref' } function Invoke-InfobloxQuery { [CmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory)][string] $BaseUri, [parameter(Mandatory)][string] $RelativeUri, [parameter(Mandatory)][pscredential] $Credential, [parameter()][System.Collections.IDictionary] $QueryParameter, [parameter()][string] $Method = 'GET', [parameter()][System.Collections.IDictionary] $Body ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Invoke-InfobloxQuery - You must first connect to an Infoblox server using Connect-Infoblox' return } $joinUriQuerySplat = @{ BaseUri = $BaseUri RelativeOrAbsoluteUri = $RelativeUri } if ($QueryParameter) { $joinUriQuerySplat['QueryParameter'] = $QueryParameter } # if ($Method -eq 'GET') { # if (-not $QueryParameter) { # $joinUriQuerySplat['QueryParameter'] = [ordered] @{} # } # #_paging = 1 # #_return_as_object = 1 # #_max_results = 100000 # $joinUriQuerySplat['QueryParameter']._max_results = 1000000 # } $Url = Join-UriQuery @joinUriQuerySplat if ($PSCmdlet.ShouldProcess($Url, "Invoke-InfobloxQuery - $Method")) { Write-Verbose -Message "Invoke-InfobloxQuery - Querying $Url with $Method" # $WebSession = New-WebSession -Cookies @{ # timeout = 600 # mtime = 144631868 # client = 'API' # } -For $BaseUri try { $invokeRestMethodSplat = @{ Uri = $Url Method = $Method Credential = $Credential ContentType = 'application/json' ErrorAction = 'Stop' Verbose = $false #WebSession = $WebSession TimeoutSec = 600 } if ($Body) { $invokeRestMethodSplat.Body = $Body | ConvertTo-Json -Depth 10 } Remove-EmptyValue -Hashtable $invokeRestMethodSplat -Recursive -Rerun 2 Invoke-RestMethod @invokeRestMethodSplat } catch { if ($ErrorActionPreference -eq 'Stop') { throw } Write-Warning -Message "Invoke-InfobloxQuery - Querying $Url failed. Error: $($_.Exception.Message)" } } } function Remove-InfobloxFixedAddress { [cmdletbinding(SupportsShouldProcess)] param( [parameter(Mandatory)][string] $MacAddress, [parameter()][string] $IPv4Address ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Remove-InfobloxFixedAddress - You must first connect to an Infoblox server using Connect-Infoblox' return } if (-not $IPv4Address) { Write-Verbose -Message "Remove-InfobloxFixedAddress - Removing $MacAddress" } else { Write-Verbose -Message "Remove-InfobloxFixedAddress - Removing $MacAddress from $IPv4Address" } $ListMacaddresses = Get-InfobloxFixedAddress -MacAddress $MacAddress if ($IPv4Address) { $ListMacaddresses = $ListMacaddresses | Where-Object -Property ipv4addr -EQ -Value $IPv4Address } foreach ($Mac in $ListMacaddresses) { $invokeInfobloxQuerySplat = @{ RelativeUri = "$($Mac._ref)" Method = 'DELETE' } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Remove-InfobloxFixedAddress - Removed $($Mac.ipv4addr) with mac address $($Mac.mac) / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Remove-InfobloxFixedAddress - Failed to remove $($Mac.ipv4addr) with mac address $($Mac.mac), error: $varWarning" } } } } function Remove-InfobloxIPAddress { [cmdletbinding(SupportsShouldProcess)] param( [parameter()][string] $IPv4Address ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Remove-InfobloxIPAddress - You must first connect to an Infoblox server using Connect-Infoblox' return } Write-Verbose -Message "Remove-InfobloxIPAddress - Removing $IPv4Address" $ListIP = Get-InfobloxIPAddress -IPv4Address $IPv4Address foreach ($IP in $ListIP) { $invokeInfobloxQuerySplat = @{ RelativeUri = "$($IP._ref)" Method = 'DELETE' } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Remove-InfobloxIPAddress - Removed $($IP.ip_address) from network $($IP.network) / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Remove-InfobloxIPAddress - Failed to remove $($IP.ip_address) with mac address $($IP.network), error: $varWarning" } } } } function Remove-InfobloxObject { <# .SYNOPSIS Remove an Infoblox object by reference ID .DESCRIPTION Remove an Infoblox object by reference ID It can be used to remove any object type, but it is recommended to use the more specific cmdlets .PARAMETER Objects An array of objects to remove .PARAMETER ReferenceID The reference ID of the object to remove .EXAMPLE Remove-InfobloxObject -ReferenceID 'record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5pbmZvLmhvc3Q6MTcyLjI2LjEuMjAu:' .NOTES General notes #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ReferenceID')] param( [Parameter(Mandatory, ParameterSetName = 'Array')][Array] $Objects, [parameter(Mandatory, ParameterSetName = 'ReferenceID')][string] $ReferenceID ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Remove-InfobloxObject - You must first connect to an Infoblox server using Connect-Infoblox' return } if ($Objects) { $Objects | ForEach-Object { if ($_._ref) { $ReferenceID = $_._ref Remove-InfobloxObject -ReferenceID $ReferenceID } else { Write-Warning -Message "Remove-InfobloxObject - Object does not have a reference ID: $_" } } } else { $invokeInfobloxQuerySplat = @{ RelativeUri = $ReferenceID Method = 'DELETE' } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Remove-InfobloxObject - Removed $($ReferenceID) / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Remove-InfobloxObject - Failed to remove $ReferenceID, error: $varWarning" } } } } function Set-InfobloxDNSRecord { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER ReferenceID Parameter description .PARAMETER Object Parameter description .PARAMETER Type Parameter description .EXAMPLE Set-InfobloxDNSRecord -ReferenceID 'record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5teW5ldC5jb20kMTAuMTAuMTAuMTA=' -Name 'xyz' -Type 'A' .EXAMPLE Set-InfobloxDNSRecord -ReferenceID 'record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5teW5ldC5jb20kMTAuMTAuMTAuMTA=' -PTRName 'xyz -Type 'PTR' .EXAMPLE Set-InfobloxDNSRecord -ReferenceID 'record:host/ZG5zLmhvc3QkLl9kZWZhdWx0LmNvbS5teW5ldC5jb20kMTAuMTAuMTAuMTA=' -Name 'test2.mcdonalds.com' -Type 'CNAME' .NOTES General notes #># [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ReferenceID')] param( [parameter(ParameterSetName = 'ReferenceID', Mandatory)][string] $ReferenceID, [Alias("Name", 'PtrName', 'PTR', 'NameServer', 'Text')][parameter(ParameterSetName = 'Object', Mandatory)][string] $Object, [parameter(Mandatory)][ValidateSet( 'A', 'AAAA', 'CNAME', 'HOST', 'PTR', 'MX', 'NS', 'TXT' )][string] $Type ) if (-not $Script:InfobloxConfiguration) { if ($ErrorActionPreference -eq 'Stop') { throw 'You must first connect to an Infoblox server using Connect-Infoblox' } Write-Warning -Message 'Set-InfobloxDNSRecord - You must first connect to an Infoblox server using Connect-Infoblox' return } # Lets convert it to lowercase, since Infoblox is case sensitive $Type = $Type.ToLower() if ($Type -in 'A', 'AAAA', 'HOST', 'CNAME', 'MX') { $Body = [ordered] @{ name = $Object.ToLower() } } elseif ($Type -eq 'PTR') { $Body = [ordered] @{ ptrdname = $Object.ToLower() } } elseif ($Type -eq 'NS') { $Body = [ordered] @{ nameserver = $Object.ToLower() } } elseif ($Type -eq 'TXT') { $Body = [ordered] @{ text = $Object.ToLower() } } else { if ($ErrorActionPreference -eq 'Stop') { throw "Set-InfobloxDNSRecord - Unsupported type: $Type" } Write-Warning -Message "Set-InfobloxDNSRecord - Unsupported type: $Type" return } $invokeInfobloxQuerySplat = @{ RelativeUri = $ReferenceID Method = 'PUT' Body = $Body } $Output = Invoke-InfobloxQuery @invokeInfobloxQuerySplat -WarningAction SilentlyContinue -WarningVariable varWarning if ($Output) { Write-Verbose -Message "Set-InfobloxDNSRecord - Modified $Type / $Output" } else { if (-not $WhatIfPreference) { Write-Warning -Message "Set-InfobloxDNSRecord - Failed to modify $Type, error: $varWarning" } } } # Export functions and aliases as required Export-ModuleMember -Function @('Add-InfoBloxDNSRecord', 'Add-InfobloxFixedAddress', 'Connect-Infoblox', 'Disconnect-Infoblox', 'Get-InfobloxDHCPLease', 'Get-InfobloxDHCPRange', 'Get-InfobloxDiscoveryTask', 'Get-InfobloxDNSAuthZone', 'Get-InfobloxDNSDelegatedZone', 'Get-InfobloxDNSForwardZone', 'Get-InfobloxDNSRecord', 'Get-InfobloxDNSRecordAll', 'Get-InfobloxDNSView', 'Get-InfobloxFixedAddress', 'Get-InfobloxGrid', 'Get-InfobloxIPAddress', 'Get-InfobloxMember', 'Get-InfobloxNetwork', 'Get-InfobloxNetworkNextAvailableIP', 'Get-InfobloxNetworkView', 'Get-InfobloxObjects', 'Get-InfobloxPermission', 'Get-InfobloxResponsePolicyZones', 'Get-InfobloxSchema', 'Get-InfoBloxSearch', 'Get-InfobloxVDiscoveryTask', 'Invoke-InfobloxQuery', 'Remove-InfobloxFixedAddress', 'Remove-InfobloxIPAddress', 'Remove-InfobloxObject', 'Set-InfobloxDNSRecord') -Alias @('Get-InfobloxDHCPLeases', 'Get-InfobloxDNSAuthZones', 'Get-InfobloxDNSRecords', 'Get-InfobloxDNSRecordsAll') # SIG # Begin signature block # MIItsQYJKoZIhvcNAQcCoIItojCCLZ4CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAozOwh5pJT6/6L # zIiQRHY6x8wnx1Z5WIQtgpJthV4EfaCCJrQwggWNMIIEdaADAgECAhAOmxiO+dAt # 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa # Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD # ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E # MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy # unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF # xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1 # 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB # MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR # WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6 # nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB # YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S # UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x # q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB # NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP # TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC # AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp # Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv # bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0 # aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB # LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc # Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov # Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy # oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW # juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF # mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z # twGpn1eqXijiuZQwggWQMIIDeKADAgECAhAFmxtXno4hMuI5B72nd3VcMA0GCSqG # SIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx # GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy # dXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL/mkHNo3rvkXUo8MCIw # aTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/zG6Q4FutWxpdtHauyefLK # EdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZanMylNEQRBAu34LzB4Tm # dDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7sWxq868nPzaw0QF+xembu # d8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL2pNe3I6PgNq2kZhAkHnD # eMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfbBHMqbpEBfCFM1LyuGwN1 # XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3JFxGj2T3wWmIdph2PVld # QnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3cAORFJYm2mkQZK37AlLTS # YW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqxYxhElRp2Yn72gLD76GSm # M9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0viastkF13nqsX40/ybzT # QRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aLT8LWRV+dIPyhHsXAj6Kx # fgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD # VR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwPTzANBgkq # hkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNkaA9Wz3eucPn9mkqZucl4 # XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjSPMFDQK4dUPVS/JA7u5iZ # aWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK7VB6fWIhCoDIc2bRoAVg # X+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eBcg3AFDLvMFkuruBx8lbk # apdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp5aPNoiBB19GcZNnqJqGL # FNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msgdDDS4Dk0EIUhFQEI6FUy # 3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vriRbgjU2wGb2dVf0a1TD9u # KFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ79ARj6e/CVABRoIoqyc54 # zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5nLGbsQAe79APT0JsyQq8 # 7kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3i0objwG2J5VT6LaJbVu8 # aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0HEEcRrYc9B9F1vM/zZn4w # ggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBH # NDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1 # c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqG # SIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbS # g9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9 # /UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXn # HwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0 # VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4f # sbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUmcJgmf6AaRyBD40Nj # gHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0 # QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvv # mz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T # /jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk # 42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXcheMBK9Rp6103a50g5r # mQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E # FgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5n # P+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcG # CCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQu # Y29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGln # aUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8v # Y3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNV # HSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIB # AH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxp # wc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIl # zpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQ # cAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfe # Kuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+j # Sbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJsh # IUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6 # OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDw # N7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR # 81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2 # VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIGsDCCBJigAwIBAgIQ # CK1AsmDSnEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEV # MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t # MSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAw # MDAwWhcNMzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBT # aWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEF # AAOCAg8AMIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+k # jmjYXPXrNCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9 # NH1MgFcSa0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9 # URnokCF4RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegY # E2XFf7JPhSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS # 4+jWufcx4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJa # wv9qYFSLScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+w # c86LJiUGsoPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eR # Gv7bUKJGyGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF2 # 3r9Yy3IQKUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCK # ZFTBzCEa6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhEC # AwEAAaOCAVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2 # O/hfEYb7/mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P # MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcB # AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr # BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1 # c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAH # BgVngQwBAzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6 # mdNW4AIapfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/ # SfQnuxaBRVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzY # gBoRGRjNYZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9 # kNF2ht0csGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ # 9d3OVG3ZXQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAew # Q3+ViCCCcPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5Lm # Tl/eeqxJzy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HA # SIRLlk2rREDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xr # y7fwdxPm5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhR # ILutG4UI4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFu # v2jiJmCG6sivqf6UHedjGzqGVnhOMIIGwjCCBKqgAwIBAgIQBUSv85SdCDmmv9s/ # X+VhFjANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGln # aUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5 # NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIzMDcxNDAwMDAwMFoXDTM0MTAx # MzIzNTk1OVowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMzCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBAKNTRYcdg45brD5UsyPgz5/X5dLnXaEOCdwvSKOX # ejsqnGfcYhVYwamTEafNqrJq3RApih5iY2nTWJw1cb86l+uUUI8cIOrHmjsvlmbj # aedp/lvD1isgHMGXlLSlUIHyz8sHpjBoyoNC2vx/CSSUpIIa2mq62DvKXd4ZGIX7 # ReoNYWyd/nFexAaaPPDFLnkPG2ZS48jWPl/aQ9OE9dDH9kgtXkV1lnX+3RChG4PB # uOZSlbVH13gpOWvgeFmX40QrStWVzu8IF+qCZE3/I+PKhu60pCFkcOvV5aDaY7Mu # 6QXuqvYk9R28mxyyt1/f8O52fTGZZUdVnUokL6wrl76f5P17cz4y7lI0+9S769Sg # LDSb495uZBkHNwGRDxy1Uc2qTGaDiGhiu7xBG3gZbeTZD+BYQfvYsSzhUa+0rRUG # FOpiCBPTaR58ZE2dD9/O0V6MqqtQFcmzyrzXxDtoRKOlO0L9c33u3Qr/eTQQfqZc # ClhMAD6FaXXHg2TWdc2PEnZWpST618RrIbroHzSYLzrqawGw9/sqhux7UjipmAmh # cbJsca8+uG+W1eEQE/5hRwqM/vC2x9XH3mwk8L9CgsqgcT2ckpMEtGlwJw1Pt7U2 # 0clfCKRwo+wK8REuZODLIivK8SgTIUlRfgZm0zu++uuRONhRB8qUt+JQofM604qD # y0B7AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAW # BgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglg # hkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0O # BBYEFKW27xPn783QZKHVVqllMaPe1eNJMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6 # Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEy # NTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUF # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6 # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZT # SEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAIEa1t6g # qbWYF7xwjU+KPGic2CX/yyzkzepdIpLsjCICqbjPgKjZ5+PF7SaCinEvGN1Ott5s # 1+FgnCvt7T1IjrhrunxdvcJhN2hJd6PrkKoS1yeF844ektrCQDifXcigLiV4JZ0q # BXqEKZi2V3mP2yZWK7Dzp703DNiYdk9WuVLCtp04qYHnbUFcjGnRuSvExnvPnPp4 # 4pMadqJpddNQ5EQSviANnqlE0PjlSXcIWiHFtM+YlRpUurm8wWkZus8W8oM3NG6w # QSbd3lqXTzON1I13fXVFoaVYJmoDRd7ZULVQjK9WvUzF4UbFKNOt50MAcN7MmJ4Z # iQPq1JE3701S88lgIcRWR+3aEUuMMsOI5ljitts++V+wQtaP4xeR0arAVeOGv6wn # LEHQmjNKqDbUuXKWfpd5OEhfysLcPTLfddY2Z1qJ+Panx+VPNTwAvb6cKmx5Adza # ROY63jg7B145WPR8czFVoIARyxQMfq68/qTreWWqaNYiyjvrmoI1VygWy2nyMpqy # 0tg6uLFGhmu6F/3Ed2wVbK6rr3M66ElGt9V/zLY4wNjsHPW2obhDLN9OTH0eaHDA # dwrUAuBcYLso/zjlUlrWrBciI0707NMX+1Br/wd3H3GXREHJuEbTbDJ8WC9nR2Xl # G3O2mflrLAZG70Ee8PBf4NvZrZCARK+AEEGKMIIHXzCCBUegAwIBAgIQB8JSdCgU # otar/iTqF+XdLjANBgkqhkiG9w0BAQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UE # ChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQg # Q29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMB4XDTIzMDQxNjAw # MDAwMFoXDTI2MDcwNjIzNTk1OVowZzELMAkGA1UEBhMCUEwxEjAQBgNVBAcMCU1p # a2/FgsOzdzEhMB8GA1UECgwYUHJ6ZW15c8WCYXcgS8WCeXMgRVZPVEVDMSEwHwYD # VQQDDBhQcnplbXlzxYJhdyBLxYJ5cyBFVk9URUMwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCUmgeXMQtIaKaSkKvbAt8GFZJ1ywOH8SwxlTus4McyrWmV # OrRBVRQA8ApF9FaeobwmkZxvkxQTFLHKm+8knwomEUslca8CqSOI0YwELv5EwTVE # h0C/Daehvxo6tkmNPF9/SP1KC3c0l1vO+M7vdNVGKQIQrhxq7EG0iezBZOAiukNd # GVXRYOLn47V3qL5PwG/ou2alJ/vifIDad81qFb+QkUh02Jo24SMjWdKDytdrMXi0 # 235CN4RrW+8gjfRJ+fKKjgMImbuceCsi9Iv1a66bUc9anAemObT4mF5U/yQBgAuA # o3+jVB8wiUd87kUQO0zJCF8vq2YrVOz8OJmMX8ggIsEEUZ3CZKD0hVc3dm7cWSAw # 8/FNzGNPlAaIxzXX9qeD0EgaCLRkItA3t3eQW+IAXyS/9ZnnpFUoDvQGbK+Q4/bP # 0ib98XLfQpxVGRu0cCV0Ng77DIkRF+IyR1PcwVAq+OzVU3vKeo25v/rntiXCmCxi # W4oHYO28eSQ/eIAcnii+3uKDNZrI15P7VxDrkUIc6FtiSvOhwc3AzY+vEfivUkFK # RqwvSSr4fCrrkk7z2Qe72Zwlw2EDRVHyy0fUVGO9QMuh6E3RwnJL96ip0alcmhKA # BGoIqSW05nXdCUbkXmhPCTT5naQDuZ1UkAXbZPShKjbPwzdXP2b8I9nQ89VSgQID # AQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHQYD # VR0OBBYEFHrxaiVZuDJxxEk15bLoMuFI5233MA4GA1UdDwEB/wQEAwIHgDATBgNV # HSUEDDAKBggrBgEFBQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3Js # My5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQw # OTZTSEEzODQyMDIxQ0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAy # MUNBMS5jcmwwPgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0 # cDovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGUBggrBgEFBQcBAQSBhzCBhDAkBggr # BgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFwGCCsGAQUFBzAChlBo # dHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2Rl # U2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0ExLmNydDAJBgNVHRMEAjAAMA0GCSqG # SIb3DQEBCwUAA4ICAQC3EeHXUPhpe31K2DL43Hfh6qkvBHyR1RlD9lVIklcRCR50 # ZHzoWs6EBlTFyohvkpclVCuRdQW33tS6vtKPOucpDDv4wsA+6zkJYI8fHouW6Tqa # 1W47YSrc5AOShIcJ9+NpNbKNGih3doSlcio2mUKCX5I/ZrzJBkQpJ0kYha/pUST2 # CbE3JroJf2vQWGUiI+J3LdiPNHmhO1l+zaQkSxv0cVDETMfQGZKKRVESZ6Fg61b0 # djvQSx510MdbxtKMjvS3ZtAytqnQHk1ipP+Rg+M5lFHrSkUlnpGa+f3nuQhxDb7N # 9E8hUVevxALTrFifg8zhslVRH5/Df/CxlMKXC7op30/AyQsOQxHW1uNx3tG1DMgi # zpwBasrxh6wa7iaA+Lp07q1I92eLhrYbtw3xC2vNIGdMdN7nd76yMIjdYnAn7r38 # wwtaJ3KYD0QTl77EB8u/5cCs3ShZdDdyg4K7NoJl8iEHrbqtooAHOMLiJpiL2i9Y # n8kQMB6/Q6RMO3IUPLuycB9o6DNiwQHf6Jt5oW7P09k5NxxBEmksxwNbmZvNQ65Z # n3exUAKqG+x31Egz5IZ4U/jPzRalElEIpS0rgrVg8R8pEOhd95mEzp5WERKFyXhe # 6nB6bSYHv8clLAV0iMku308rpfjMiQkqS3LLzfUJ5OHqtKKQNMLxz9z185UCszGC # BlMwggZPAgEBMH0waTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS # U0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQB8JSdCgUotar/iTqF+XdLjANBglghkgB # ZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJ # AzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8G # CSqGSIb3DQEJBDEiBCBJUhYcKX1Wy2tKXiFEUzzTJXIJ4oS7xke7KpTpEd0n/zAN # BgkqhkiG9w0BAQEFAASCAgAeZ9KppfKC6stXGdrMVG+x4ouy333RGytHDwyVKUxd # rjpTgMDzlgYDyu/T9NE0XETVhRqg9dWonzsOuahyyqfAJpjN2nScMMqL/O7MOpjO # 4MNGqgL8NIT8TRiq1yHVn7ZXqr0Q91Tjh6Cb/Zd0GtwMFWreAAy18xdg3DFBSeax # lOroeEYsvkQnB+winAxPjvluj2cy37yZHd+wr0KujRbc1NUl/AWXQ+GI5icrFKIf # KjFocxy0sPKQ2xwt5bj0AkTOfEEE8obM9la/hiUCyfpI7Dz2KNkLqylatXf/mhDX # I9Ieag5i2TcbcSyqOEN03D0OuPINYoGFptCp1QBat+WA2WxDdmb4QTwN3j+R8AB1 # jEBypdzTQFvfk39jJ5rn1VJ+b8T5dx0DJbTxEk099nMkGGpRLkawAy+zzykxOVuj # IMKqPm2DFAjahXINyfbXFn5bTMbw2XnzjHyPR5zJpgdOvDib4nQvkhzt/xf9EVu3 # cg9uqhO5oLQswmeaGOhFCNLu4SZfU3cSVrBE5qkR+Dxt7rB813+Rgq9+r4pWO26L # XEsJa4YU2Vkl2UPspBFE3TsbEZS0C+DfstTxlFK/kJLyhhfw3HgO96I8YM+de1wZ # MdG0CFA1ez7B8Trek4LjGcjbQKr6dtUGkyMVG1ew6R6Vk4qzVcvHu27MSfK25QAi # BqGCAyAwggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJBgNVBAYTAlVT # MRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1 # c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAVEr/OUnQg5 # pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcN # AQcBMBwGCSqGSIb3DQEJBTEPFw0yNDAzMDYwODE4MzZaMC8GCSqGSIb3DQEJBDEi # BCBoi/5xM8PS/e9NpAPco+cwMXomEfRNMzucrfT36k2rbjANBgkqhkiG9w0BAQEF # AASCAgBopiWgd7c8a1uvP76D6wn9gPc88Vry/5EO04rC89yH8+SN/Y81NqLvupfN # Ycq7F8VCLICFFBYlw+IOHFaxIMxwLVvjG+GKWfSCSNShyxM3OzKoLwRYYHn28G4m # rtdxpvMqFihjlwO7m6AUwQlWRf9U04r/U5pMDX41bVUI1df/z6Z1KFCMETlTQ515 # +cS4nPIYCZYhrev91VpHTVQbrsL+y1jcalylMOUBLvKuN3oyvr4Xuim6rKRHsjW0 # B/x7ZeBQXi3HRb7MZlRmw2X46u8pim9liMO6sCuTlTOsCiefMr5mAdIWF82QhNXt # sWcUmvDcUbNiIkh0WVU7y9VET/l99eFA1XuklMAU+UTsswA/gmjkLV/QRECLRT7b # C/+XTdQKvCDwHIgjHJLX/gMZ6tLwl/4jIExbhmQXBSnzIxq3grv+6hA3n2+sFYyr # PnWoAXeztUydEVLjozC0rM6g2K3QjOhayXssamQGQH+YWOR90PnUIIr6BxaB7/KK # dxv2WPX2Xwz+KzXcnmIuK7D4uKZGG7KgqkVlDmihGcs6tGjTBEs9vbXbHzJrnAfh # 5RW+YT8u+AxXWEWgfjSmyvAfApvuHm6ksaJianJ5WlJ9ACFy5t05B0Ogst81toLi # h8nk0HSb32ct9d5An7SJoONflrKW2XiNskxqonVE7AAOChzWOA== # SIG # End signature block |