powershell
9 TopicsPowerShell module for the F5 LTM REST API
Problem this snippet solves: To report an issue with the F5-LTM or F5-BIGIP modules, please use the Issues sections of the GitHub repos (here and here) instead of commenting here. Thanks! This PowerShell module uses the iControlREST API to manipulate and query pools, pool members, virtual servers, and iRules. It aims to support version 11.5.1 and higher, and to conform to the schedule for technical support of versions, though this may eventually prove to become difficult. The module currently includes some functionality that, strictly speaking, is outside the scope of the LTM module. Hence, there is an active effort to wrap this LTM module into a larger BIG-IP module, and relocate that functionality elsewhere within that parent module, as well as expand the scope of functionality to include BIG-IP DNS (formerly GTM) and possibly other areas. Both the LTM module and the parent BIG-IP module are projects on github. Please use these projects to report any issues you discover. Thanks! The module contains the following functions. Add-iRuleToVirtualServer Add-iRuleToVirtualServer Add-PoolMember Add-PoolMonitor Disable-PoolMember Disable-VirtualServer Enable-PoolMember Enable-VirtualServer Get-CurrentConnectionCount (deprecated; use Get-PoolMemberStats | Select-Object -ExpandProperty 'serverside.curConns') Get-F5Session (will be deprecated in future versions. use New-F5Session) Get-F5Status Get-HealthMonitor Get-HealthMonitorType Get-iRule Get-iRuleCollection (deprecated; use Get-iRule) Get-Node Get-BIGIPPartition Get-Pool Get-PoolList (deprecated; use Get-Pool) Get-PoolMember Get-PoolMemberCollection (deprecated; use Get-PoolMember) Get-PoolMemberCollectionStatus Get-PoolMemberDescription (deprecated; use Get-PoolMember) Get-PoolMemberIP (deprecated; use Get-PoolMember) Get-PoolMembers (deprecated; use Get-PoolMember) Get-PoolMemberStats Get-PoolMemberStatus (deprecated; use Get-PoolMember) Get-PoolMonitor Get-PoolsForMember Get-StatusShape Get-VirtualServer Get-VirtualServeriRuleCollection (deprecated; use Get-VirtualServer | Where rules | Select -ExpandProperty rules) Get-VirtualServerList (deprecated; use Get-VirtualServer) Invoke-RestMethodOverride New-F5Session New-HealthMonitor New-Node New-Pool New-VirtualServer Remove-HealthMonitor Remove-iRule Remove-iRuleFromVirtualServer Remove-Pool Remove-PoolMember Remove-PoolMonitor Remove-ProfileRamCache Remove-Node Remove-VirtualServer Set-iRule Set-PoolLoadBalancingMode (deprecated; use Set-Pool) Set-PoolMemberDescription Set-Pool Set-VirtualServer Sync-DeviceToGroup Test-F5Session Test-Functionality Test-HealthMonitor Test-Node Test-Pool Test-VirtualServer How to use this snippet: To use the module, click 'Download Zip', extract the files, and place them in a folder named F5-LTM beneath your PowerShell modules folder. By default, this is %USERPROFILE%\Documents\WindowsPowerShell\Modules. The WindowsPowerShell and Modules folders may need to be created. You will most likely need to unblock the files after extracting them. Use the Unblock-File PS cmdlet to accomplish this. The Validation.cs class file (based on code posted by Brian Scholer) allows for using the REST API with LTM devices with self-signed SSL certificates. Nearly all of the functions require an F5 session object as a parameter, which contains the base URL for the F5 LTM and a credential object for a user with privileges to manipulate the F5 LTM via the REST API. Use the New-F5session function to create this object. This function expects the following parameters: The name or IP address of the F5 LTM device A credential object for a user with rights to use the REST API An optional TokenLifespan value for extending the life of the authentication token past the default 20 minutes You can create a credential object using Get-Credential and entering the username and password at the prompts, or programmatically like this: $secpasswd = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force $mycreds = New-Object System.Management.Automation.PSCredential "username", $secpasswd Thanks to Kotesh Bandhamravuri and his blog entry for this snippet. There is a function called Test-Functionality that takes an F5Session object, a new pool name, a new virtual server, an IP address for the virtual server, and a computer name as a pool member, and validates nearly all the functions in the module. I've also contributed this code sample for how to gather some basic info about your LTM with this PS module. The module has been tested on: 11.5.1 Build 8.0.175 Hotfix 8 and later 11.6.0 Build 5.0.429 Hotfix 4 and later 12.0 / 12.1 13.0 Code : https://github.com/joel74/POSH-LTM-Rest Tested this on version: 11.519KViews2likes150CommentsPowerShell - Get a list of VIPs and SSL profiles (client and server)
Problem this snippet solves: Having had numerous occasions where I needed to figure out where a particular SSL profile was assigned and seeing a few similar questions here on DC, I decided to make use of PowerShell and iControlRest to get that data for me. This script allows you to grab all the VIPs on the box and list the SSL profiles (both client and server) associated with them. How to use this snippet: Prerequisites: You will need to be on BIG-IP v11.4 or newer, as that's when iControlRest was introduced. You will also need a Windows machine and PowerShell v3 or newer (v4 or v5). Paste this code into your PowerShell console and then run it with at least the hostname (or IP) of your BIG-IP, and it will prompt you for credentials and return the list of VIPs and SSL profiles. Note: If you use an IP address, you should really include the -IgnoreCertErrors flag as well, since it won't work by default without a valid cert Examples: Get-F5VipsAndSslProfiles mybigip.example.com; Get-F5VipsAndSslProfiles 10.10.10.10 -IgnoreCertErrors; Get-F5VipsAndSslProfiles -f5HostIp mybigip.example.com; Get-F5VipsAndSslProfiles -f5HostIp 10.10.10.10 -IgnoreCertErrors; $cred = (Get-Credentials); Get-F5VipsAndSslProfiles -f5HostIp 10.10.10.10 -f5Cred $cred -IgnoreCertErrors; Code : function Get-F5VipsAndSslProfiles($f5HostIp, $f5Cred, [switch]$IgnoreCertErrors = $false) { $f5Host = "https://$f5HostIp/mgmt/tm"; if ($IgnoreCertErrors) { Add-Type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@; [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy; } $sslProfilesClient = $(Invoke-RESTMethod -Method GET -Uri "$($f5Host)/ltm/profile/client-ssl?`$select=name,partition,fullPath" -Credential $f5Cred).items | Select-Object -ExpandProperty FullPath; $sslProfilesServer = $(Invoke-RESTMethod -Method GET -Uri "$($f5Host)/ltm/profile/server-ssl?`$select=name,partition,fullPath" -Credential $f5Cred).items | Select-Object -ExpandProperty FullPath; $virtualServers = $(Invoke-RESTMethod -Method GET -Uri "$($f5Host)/ltm/virtual?expandSubcollections=true&`$select=name,partitioclsn,fullPath,profilesReference" -Credential $f5Cred); $virtualServers.items | Select-Object Name, FullPath, ` @{Name="ClientSslProfiles"; Expression={($_.profilesReference.items | ?{ $sslProfilesClient -contains $_.fullPath -and $_.context -eq "clientside" }) | Select -ExpandProperty fullPath }}, ` @{Name="ServerSslProfiles"; Expression={($_.profilesReference.items | ?{ $sslProfilesServer -contains $_.fullPath -and $_.context -eq "serverside" }) | Select -ExpandProperty fullPath }}; } Tested this on version: 11.51.8KViews0likes2CommentsPowerShell to iRule AES-CBC conversation using random IV values
Problem this snippet solves: Hi Folks, I saw recently on the DevCentral boards that people are struggeling to securely exchange AES encrypted information between a Windows System and LTM. Although some DevCentral members already managed it by using static IV (Initialization Vectors) on both sites, this approach should be considered as a very bad practise, since it allows an adversary to pulloff certain crypto analyses/attacks which could already lead to a security breach. The snippets below will outline how to implement AES-CBC decryption/encryption with dynamic IV values on Windows using PowerShell and on LTM using iRules. The outlined snippets are alligned to each other by using the same AES crypto settings (Key-Size, Block-Size, CBC-Mode and Padding-Mode) and IV exchange techniques to become interoperable. The implemented IV exchange technique will generate a fresh and random IV on each single encryption and simply prepended the AES-IV to the AES-Ciphertext before passing it to the receiver. The receiver then splits the received AES-Cipherstring into the contained AES-IV and AES-Ciphertext values and finally decrypt the AES-Ciphertext by using the shared AES-Key. From Windows to LTM 1. Import the follwing PS functions on the Windows side function Create-AesKey($KeySize) { $AesManaged = New-Object "System.Security.Cryptography.AesManaged" $AesManaged.KeySize = $KeySize $AesManaged.GenerateKey() [System.Convert]::ToBase64String($AesManaged.Key) } function Encrypt-Data($AesKey, $Data) { $Data = [System.Text.Encoding]::UTF8.GetBytes($Data) $AesManaged = New-Object "System.Security.Cryptography.AesManaged" $AesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC $AesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 $AesManaged.BlockSize = 128 $AesManaged.KeySize = 256 $AesManaged.Key = [System.Convert]::FromBase64String($AesKey) $Encryptor = $AesManaged.CreateEncryptor() $EncryptedData = $Encryptor.TransformFinalBlock($Data, 0, $Data.Length); [byte[]] $EncryptedData = $AesManaged.IV + $EncryptedData $AesManaged.Dispose() [System.Convert]::ToBase64String($EncryptedData) } function Decrypt-Data($AesKey, $Data) { $Data = [System.Convert]::FromBase64String($Data) $AesManaged = New-Object "System.Security.Cryptography.AesManaged" $AesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC $AesManaged.Padding = [System.Security.Cryptography.PaddingMode]::PKCS7 $AesManaged.BlockSize = 128 $AesManaged.KeySize = 256 $AesManaged.IV = $Data[0..15] $AesManaged.Key = [System.Convert]::FromBase64String($AesKey) $Decryptor = $AesManaged.CreateDecryptor(); $DecryptedData = $Decryptor.TransformFinalBlock($Data, 16, $Data.Length - 16); $aesManaged.Dispose() [System.Text.Encoding]::UTF8.GetString($DecryptedData) } 2. Generate a fresh 256bit AESKey on your Windows System and store it locally as well as on your F5. Create-AesKey 256 iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU= 3. Encrypt some data using the AES-Shared-Key $encrypted = Encrypt-Data " iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU=" "Hello World!" $encrypted W5xFrWz72U/vt95HG6fHWIuDDHpuhj2HB42E4SIrNwo= Note: Every single encryption should have a different outcome. Thanks to the random IV! 4. Pass the AES-Cipherstring to your LTM and decrypt it using the snippet below set aes_key [b64decode "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU="] set aes_cipherstring [b64decode "W5xFrWz72U/vt95HG6fHWIuDDHpuhj2HB42E4SIrNwo="] binary scan $aes_cipherstring a16a* aes_iv aes_ciphertext set aes_plaintext [CRYPTO::decrypt -alg aes-256-cbc -key $aes_key -iv $aes_iv $aes_ciphertext] log local0.debug "Plaintext = $aes_plaintext" Log Output : Plaintext = Hello World! From LTM to Windows 1. AES encrypt some data on your LTM using the snippet below set aes_key [b64decode "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU="] set aes_plaintext "Hello World!!" set aes_iv [CRYPTO::keygen -alg random -passphrase "MyIVSeed" -len 128] set aes_ciphertext [CRYPTO::encrypt -alg aes-256-cbc -key $aes_key -iv $aes_iv $aes_plaintext] set aes_cipherstring [b64encode [binary format a*a* $aes_iv $aes_ciphertext]] log local0.debug "Cipherstring = $aes_cipherstring" Log Output : Cipherstring = vCIizWalo4KWO+3bLuTUp5iD0J3kArrcZS1fKDue89M= Note: Every single encryption should also have a different outcome. Thanks to the random IV! 2. Pass the AES-Cipherstring to your Windows system and decrypt it using the snippet below $decrypted = Decrypt-Data "iTEEieok7//RyzrPe5mWwz1yroPPsm4e5cqghdEHIlU=" "vCIizWalo4KWO+3bLuTUp5iD0J3kArrcZS1fKDue89M=" $decrypted Hello World!! Cheers, Kai How to use this snippet: See above... Code : See above...1.4KViews0likes0CommentsF5 BIGIP Management Pack for SCOM 2012 R2 ( free, source open )
Problem this snippet solves: Hi, I authored a small Management Pack to monitor some key components for F5 BIGIP devices. It works with SCOM 2012 R2 and will work with 2016. Under the hood REST (authentication taught by @Joel Newton) and SNMP is used. Diagram: State: Alert: Links: Management Pack Details Management Pack Setup Management Pack Management Pack VSAE 2015 Solution Feel free to contact me :-) Kind regards Ruben Code : https://github.com/Juanito99/F5_BIGIP_OpsMgr1.4KViews0likes1CommentConnect to version 14 and above with Powershell iControl
Problem this snippet solves: Customer was asking how to connect to version 14 BigIP with PowerShell. They were previously using version 13 and everything worked with this code: Add-PSSnapin iControlSnapin; Write-Output "Initializing F5 iControl..." Initialize-F5.iControl -HostName $bigiphostname -Username $bigipuser -Password $bigippw But on version 14 it wouldn't connect. After much searching and testing I found that the BigIPReporter guy https://devcentral.f5.com/s/profile/0051T000008u1WRQAY Figured it out, and I shamelessly stole his code and made it into this shorter snippet. His larger Reporter Code can be found here https://devcentral.f5.com/s/articles/bigip-report Also for the poor sucker that is trying to find the powershell module snapin - try here - https://cdn.f5.com/websites/devcentral.f5.com/downloads/f5-icontrol-powershell-snapin-13_1_0.zip - unblock it at the file explorer level, extract and run it. Then download the github repo for the newer code from here - https://github.com/f5devcentral/f5-icontrol-powershell-snapin - saving it into the F5 directory that was created in the previous step. Then run the installation steps that are detailed in the GitHub code. How to use this snippet: Create a file called TestConnection.ps1 and copy in the code changing the values for the first three lines to reflect your environment. Code : #Change these values $BigIPUser = 'admin' $BigIPPW = 'password' $BigIPName = '192.168.0.245' #Begin Script $User = $BigIPUser $Password = $BigIPPW #Create the string that is converted to Base64 $Credentials = $User + ":" + $Password #Encode the string to base64 $EncodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Credentials)) #Add the "Basic prefix" $BasicAuthValue = "Basic $EncodedCreds" $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", $BasicAuthValue) #set the connection to TLS 1.2 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 #Create the body of the post $Body = @{"username" = $User; "password" = $Password; "loginProviderName" = "tmos" } #Convert the body to Json $Body = $Body | ConvertTo-Json $Response = Invoke-RestMethod -Method "POST" -Headers $headers -Body $Body -Uri "https://$BigIPName/mgmt/shared/authn/login" -ContentType 'application/json' Write-Output "Auth token:" Write-Output $Response.token $success = Initialize-F5.iControl -Username 'admin' -Password 'G00fy123' -HostName '192.168.3.103' Write-Output "Sucessfully innitialized BigIP: $success" $F5 = Get-F5.iControl $BigIPHostname = $F5.SystemInet.get_hostname() Write-Output "BigIP Hostname: $BigIPHostname" Tested this on version: No Version Found830Views0likes0CommentsGetting Started with iControl Code Samples
Problem this snippet solves: This repository on github is for the full scripts highlighted in the Getting Started with iControl article series. Developed against BIG-IP TMOS version 12.0, but should work in most versions 11.6+. How to use this snippet: Choose your language and iControl portal of choice to start investigating iControl in your environment. Target audience: beginners. Code : https://github.com/f5devcentral/iControl-GettingStarted Tested this on version: 12.0811Views0likes0CommentsPs BIG-IP Interactive Shell
Problem this snippet solves: This sample is the beginning of a full console-based management environment for your BIG-IP. Written in PowerShell, you are able to treat your BIG-IP just like your file system and navigate through, and act on, the objects in the system. Revision History 1.0.0 - First revision. Includes initial code for gtm.wideip, ltm.pool/poolmember/virtualserver, networking.vlan, and system.systeminfo. How to use this snippet: Setup And Running The Script Save the iControlsh.ps1 file to a directory on your system. Save the various modules to the following directory structure. installdir\iControlsh.ps1 installdir\modules\gtm\wideip.ps1 installdir\modules\ltm\pool.ps1 installdir\modules\ltm\poolmember.ps1 installdir\modules\ltm\virtualserver.ps1 installdir\modules\networking\vlan.ps1 installdir\modules\system\systeminfops1 Run the script installdir> .\iControlsh.ps1 Connect to your BIG-IP PLEASE CONNECT> : c bigip user pass bigip> : Navigate through the objects and issue some commands. At any level, type "h" for help. Files iControlsh.ps1 Code : #---------------------------------------------------------------------------- # The contents of this file are subject to the "END USER LICENSE AGREEMENT # FOR F5 Software Development Kit for iControl"; you may not use this file # except in compliance with the License. The License is included in the # iControl Software Development Kit. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is iControl Code and related documentation # distributed by F5. # # The Initial Developer of the Original Code is F5 Networks, # Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2010 # F5 Networks, Inc. All Rights Reserved. iControl (TM) is a registered # trademark of F5 Networks, Inc. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License (the "GPL"), in which case the # provisions of GPL are applicable instead of those above. If you wish # to allow use of your version of this file only under the terms of the # GPL and not to allow others to use your version of this file under the # License, indicate your decision by deleting the provisions above and # replace them with the notice and other provisions required by the GPL. # If you do not delete the provisions above, a recipient may use your # version of this file under either the License or the GPL. #---------------------------------------------------------------------------- param([switch]$Debug = $false); # Global Script variables $script:VERSION = "1.0.0"; $script:ICONTROLSH = $true; $script:DEBUG = $Debug; $script:BIGIP = ""; $script:Username = ""; $script:Password = ""; $script:Connected = $false; # Current path $script:HOSTNAME = ""; $script:CURPATH = "PLEASE CONNECT"; # Path Hashtable $script:PATHS = @{}; #---------------------------------------------------------------------------- function Debug-Message() #---------------------------------------------------------------------------- { param($msg); if ( $script:DEBUG ) { Write-Host "[DEBUG] $msg"; } } #------------------------------------------------------------------------- function Initialize-Connection() #------------------------------------------------------------------------- { param($line = $null); if ( $line ) { $tokens = $line.Split(" "); Load-Configuration; if ($tokens.length -eq 4 ) { $script:BIGIP = $tokens[1]; $script:Username = $tokens[2]; $script:Password = $tokens[3]; } if ( ($script:BIGIP.Length -gt 0) -and ($script:Username.Length -gt 0) -and ($script:Password.Length -gt 0) ) { if ( (Get-PSSnapin | Where-Object { $_.Name -eq "iControlSnapIn"}) -eq $null ) { Add-PSSnapIn iControlSnapIn } $script:Connected = Initialize-F5.iControl ` -HostName $script:BIGIP -Username $script:Username -Password $script:Password; if ( $script:Connected ) { $sysInfo = (Get-F5.iControl).SystemSystemInfo.get_system_information(); $script:CURPATH = $sysInfo.host_name; $script:HOSTNAME = $sysInfo.host_name; } } } } #---------------------------------------------------------------------------- function Exit-Console() #---------------------------------------------------------------------------- { if ( $script:Connected ) { Save-Configuration; } exit; } #---------------------------------------------------------------------------- function Validate-RegistryKey() #---------------------------------------------------------------------------- { param($Name = $null); $keyroot = "HKCU:\Software"; if ( $Null -ne $name ) { $key = Get-Item "${keyroot}\$Name" -ErrorAction silentlyContinue; if ( $null -eq $key ) { New-Item -Path "${keyroot}\$Name"; } } } #---------------------------------------------------------------------------- function Load-Configuration() #---------------------------------------------------------------------------- { $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "BIGIP" -ErrorAction SilentlyContinue; if ( $null -ne $hive ) { $script:BIGIP = $hive.BIGIP; } $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "Username" -ErrorAction SilentlyContinue; if ( $null -ne $hive ) { $script:Username = $hive.Username; } $hive = Get-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "Password" -ErrorAction SilentlyContinue; if ( $null -ne $hive ) { $script:Password = $hive.Password; } } #---------------------------------------------------------------------------- function Save-Configuration() #---------------------------------------------------------------------------- { Validate-Registrykey "F5 Networks"; Validate-RegistryKey "F5 Networks\iControlsh"; if ( $script:BIGIP.Length -gt 0 ) { Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "BIGIP" -Value $script:BIGIP; } if ( $script:Username.Length -gt 0 ) { Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "Username" -Value $script:Username; } if ( $script:Password.Length -gt 0 ) { Set-ItemProperty -Path "HKCU:\Software\F5 Networks\iControlsh" ` -Name "Password" -Value $script:Password; } } #---------------------------------------------------------------------------- function Get-CurrentPath() #---------------------------------------------------------------------------- { return $script:CURPATH; } #---------------------------------------------------------------------------- function Set-CurrentPath() #---------------------------------------------------------------------------- { param($path); $script:CURPATH = $path; } #---------------------------------------------------------------------------- function Add-ScriptPath() #---------------------------------------------------------------------------- { param($key, $value); Debug-Message "< $($MyInvocation.MyCommand.Name) >"; Debug-Message "Key = '$key'; Value = '$value'"; $v = $script:PATHS[$key]; if ( $null -eq $v ) { Debug-Message "null -eq '$v'" $script:PATHS.Add($key, $value); } else { Debug-Message "null -ne $v" $v2 = "$v,$value"; Debug-Message "Adding $key = '$v2'"; $script:PATHS[$key] = $v2; $v3 = $script:PATHS[$key]; Debug-Message "$key = '$v3'"; } } #---------------------------------------------------------------------------- function Show-Help() #---------------------------------------------------------------------------- { param([switch]$Full, $Topic = $null); $indent = " "*10; if ( $Topic -and ($Topic.Length -gt 0) ) { $key = (Get-CurrentPath).Replace($script:HOSTNAME, "icsh"); $key += "/" + $Topic; Get-Help -Full $key; } else { if ( $Full ) { Write-Host @" $indent ================================================================ $indent iControl Interactive Console Help $indent ================================================================ $indent Global Commands $indent --------------- $indent c - connect to LTM with args "bigip user pass" $indent h - print this help message. $indent i - show connection information. $indent q - exit the console. $indent r - reload the modules. "@ if ( $script:Connected ) { Write-Host @" $indent .. - Move up one level. $indent cmd - level specific command and arguments "@ } } if ( $script:Connected ) { Write-Host @" $indent Child Objects $indent ---------------- "@ $entry = (Get-HashEntry $script:PATHS) if ( $null -ne $entry ) { $children = $entry.Split(','); foreach($child in $children) { Write-Host "$indent $child"; } } Write-Host @" $indent Commands In this object $indent ----------------------- "@ $validCmds = Get-ValidCommands; foreach($cmd in $validCmds) { Write-Host "$indent $cmd"; } } } } #---------------------------------------------------------------------------- function Show-Information() #---------------------------------------------------------------------------- { Debug-Message "< $($MyInvocation.MyCommand.Name) >"; Write-Host @" Shell Version : $($script:VERSION) Connected State : $($script:Connected) BIGIP : $($script:BIGIP) Username : $($script:Username) Password : $($script:Password) Debug : $($script:DEBUG) "@ } #---------------------------------------------------------------------------- function Move-Up() #---------------------------------------------------------------------------- { Debug-Message "< $($MyInvocation.MyCommand.Name) >"; #$tokens = (Get-CurrentPath).Split(":"); $tokens = (Get-CurrentPath).Split("/"); if ($tokens.Length -gt 1) { $newpath = ""; for($i=0; $i -lt $tokens.Length-1; $i++) { #if ( $i -gt 0 ) { $newpath += ":"; } if ( $i -gt 0 ) { $newpath += "/"; } $newpath += $tokens[$i]; } if ( $newpath.Length -gt 0 ) { Set-CurrentPath $newpath; } } } #---------------------------------------------------------------------------- function Move-Down() #---------------------------------------------------------------------------- { param($subdir); Debug-Message "< $($MyInvocation.MyCommand.Name) >"; $newpath = Get-CurrentPath; #$newpath += ":"; $newpath += "/"; $newpath += $subdir; Set-CurrentPath $newpath; #Show-Help; } #---------------------------------------------------------------------------- function Get-HashEntry() #---------------------------------------------------------------------------- { param($hash, $key=(Get-CurrentPath)); $key = $key.Replace($script:HOSTNAME, "icsh"); Debug-Message "< $($MyInvocation.MyCommand.Name) '$key' >"; return $hash[$key]; } #---------------------------------------------------------------------------- function Find-HashEntry() #---------------------------------------------------------------------------- { param($cmd, $hash); Debug-Message "< $($MyInvocation.MyCommand.Name) '$cmd' >"; $valid = $false; $entry = (Get-HashEntry $hash) if ( $null -ne $entry ) { $children = $entry.Split(','); foreach($child in $children) { if ( $child -eq $cmd ) { $valid = $true; break; } } } return $valid; } #---------------------------------------------------------------------------- function Is-SubDirectory() #---------------------------------------------------------------------------- { param($cmd); Debug-Message "< $($MyInvocation.MyCommand.Name) >"; return Find-HashEntry $cmd $script:PATHS; } #---------------------------------------------------------------------------- function Get-ValidCommands() #---------------------------------------------------------------------------- { Debug-Message "< $($MyInvocation.MyCommand.Name) >"; $path = (Get-CurrentPath) $cmdPrefix = $path.Replace("$($script:HOSTNAME)", "icsh") + "/"; Debug-Message "Getting valid commands from CmdPrefix: '$cmdPrefix'"; $validCmds = Get-Command -CommandType Function "${cmdPrefix}*" | Foreach-Object -Process { $_.Name.Replace($cmdPrefix, "") } $validCmds; } #---------------------------------------------------------------------------- function Is-ValidCommand() #---------------------------------------------------------------------------- { param($cmd); Debug-Message "< $($MyInvocation.MyCommand.Name) '$cmd' >"; $bValid = $false; $validCmds = Get-ValidCommands; $tokens = $cmd.Split(" "); Debug-Message "Valid Commands"; Debug-Message $validCmds; foreach($validCmd in $validCmds) { if ( $validCmd -eq $tokens[0] ) { Debug-Message "Command '$($tokens[0])' matched '$validCmd'"; $bValid = $true; break; } } return $bValid; } #---------------------------------------------------------------------------- function Gen-FunctionName() #---------------------------------------------------------------------------- { param($cmd); Debug-Message "< $($MyInvocation.MyCommand.Name) >"; if ( $cmd ) { $path = Get-CurrentPath; $function = "icsh/"; #$tokens = $path.Split(":"); $tokens = $path.Split("/"); for($i=1; $i -lt $tokens.length; $i++) { if ( $i -gt 1 ) { $function += "/"; } $function += $tokens[$i]; } if ( $function -ne "icsh/" ) { $function += "/"; } $function += $cmd; } Debug-Message "Returning function '$function'"; return $function; } #---------------------------------------------------------------------------- function Process-Command() #---------------------------------------------------------------------------- { param($cmd); Debug-Message "< $($MyInvocation.MyCommand.Name) >"; $tokens = $cmd.Split(" "); $command = $tokens[0]; $args = ""; for($i=1; $i-lt$tokens.Length; $i++) { if ( $i -gt 1 ) { $args += " "; } $args += $tokens[$i]; } $key = $(Get-CurrentPath) + "/" + $command; $code = Gen-FunctionName $command; Debug-Message "Processing command: '$code' '$args'"; if ( $args.Length -gt 0 ) { $code += " -Opts '$args'"; } Debug-Message "Invoking code <$code>"; Invoke-Expression $code; } #---------------------------------------------------------------------------- function Get-CommandName() #---------------------------------------------------------------------------- { param($line); $cmd = $line.Trim(); $idx = $cmd.IndexOf(' '); if ( -1 -ne $idx ) { $cmd = $cmd.SubString(0, $idx).Trim(); } return $cmd; } #---------------------------------------------------------------------------- Function Get-Arguments() #---------------------------------------------------------------------------- { param($line); $args = ""; $idx = $line.Trim().IndexOf(' '); if ( -1 -ne $idx ) { $args = $line.SubString($idx+1).Trim(); } return $args; } #------------------------------------------------------------------------- function Convert-To64Bit() #------------------------------------------------------------------------- { param($high, $low); return ($high*[Math]::Pow(2,32))+$low; } #---------------------------------------------------------------------------- # Main script logic #---------------------------------------------------------------------------- $curdir = $MyInvocation.MyCommand.Path.Replace($MyInvocation.MyCommand.Name, ""); $LoadModStr = @" `$script:PATHS.Clear(); # Iterate through all the modules `$modules = Get-ChildItem `$curdir\Modules\* | Where-Object { `$_.GetType().Name -eq "DirectoryInfo" } foreach(`$module in `$modules) { `$mod = `$module.BaseName.ToLower(); Add-ScriptPath "icsh" `$mod; # iterate through the interfaces `$files = Get-ChildItem `$curdir\Modules\`$mod\* | Where-Object { `$_.GetType().Name -eq "FileInfo" } foreach(`$file in `$files) { Add-ScriptPath "icsh/`$mod" `$file.BaseName.ToLower(); Debug-Message "Invoking content for script `$(`$file.FullName)"; . `$file.FullName; } } "@; Invoke-Expression $LoadModStr; while(1) { $prompt = "$(Get-CurrentPath)> "; $i = (Read-Host $prompt).Trim(); Debug-Message "< $($MyInvocation.MyCommand.Name) '$i' >"; if ( $i.Length -gt 0 ) { Debug-Message "CommandLine: '$i'..."; switch -Wildcard ($i.ToLower()) { "" { break; } "c*" { Initialize-Connection $i; } "h*" { Show-Help -Full -Topic (Get-Arguments $i); } "i" { Show-Information; } "q" { Exit-Console; } "r" { Invoke-Expression $LoadModStr; } "d" { $script:DEBUG = -not $script:DEBUG; } "!*" { $cmd = $i.Replace("!", "").Trim(); Debug-Message "Executing command $cmd"; Invoke-Expression $cmd; } ".." { Move-Up; } default { if ( $script:Connected ) { if ( Is-SubDirectory $i ) { Move-Down $i; } elseif ( Is-ValidCommand $i ) { Process-Command $i; } else { Show-Help; } } else { Show-Help; } } } } }232Views0likes1CommentPs Object Meta Data
Problem this snippet solves: This PowerShell library will allow you to build a metadata database of information associated with objects on the system. This example uses iControl to allow you to assign metadata like Owner and Location to an object such as a VIP and then be able to query it with iControl or have access to it from within an iRule with the class command. Code : #---------------------------------------------------------------------------- # The contents of this file are subject to the "END USER LICENSE AGREEMENT FOR F5 # Software Development Kit for iControl"; you may not use this file except in # compliance with the License. The License is included in the iControl # Software Development Kit. # # Software distributed under the License is distributed on an "AS IS" # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See # the License for the specific language governing rights and limitations # under the License. # # The Original Code is iControl Code and related documentation # distributed by F5. # # The Initial Developer of the Original Code is F5 Networks, # Inc. Seattle, WA, USA. Portions created by F5 are Copyright (C) 1996-2009 F5 Networks, # Inc. All Rights Reserved. iControl (TM) is a registered trademark of F5 Networks, Inc. # # Alternatively, the contents of this file may be used under the terms # of the GNU General Public License (the "GPL"), in which case the # provisions of GPL are applicable instead of those above. If you wish # to allow use of your version of this file only under the terms of the # GPL and not to allow others to use your version of this file under the # License, indicate your decision by deleting the provisions above and # replace them with the notice and other provisions required by the GPL. # If you do not delete the provisions above, a recipient may use your # version of this file under either the License or the GPL. #---------------------------------------------------------------------------- $script:DataGroup = "ObjectMetaData"; $script:Separator = ':'; #------------------------------------------------------------------------- function New-F5.DataObject() #------------------------------------------------------------------------- { param( $Product = $null, $Type = $null, $Name = $null, $Key = $null, $Value = $null ); if ( ($Product -eq $null) -or ($Type -eq $null) -or ($Name -eq $null) -or ($Key -eq $null) -or ($Value -eq $null) ) { Write-Host "Usage: New-F5.DataObject -Product prod -Type type -Name objname -Key datakey -Value datavalue"; return; } $o = 1 | select Product, Type, Name, Key, Value; $o.Product = $Product; $o.Type = $Type; $o.Name = $Name; $o.Key = $Key; $o.Value = $Value; $o; } #------------------------------------------------------------------------- function Set-F5.MetaDataClass() #------------------------------------------------------------------------- { param($Class = $null); if ( $null -eq $Class ) { Write-Host "Usage: Set-F5.MetaDataClass -Class classname"; return; } $StringClass = New-Object -TypeName iControl.LocalLBClassStringClass; $StringClass.name = $Class $StringClass.members = (,$null); trap { if ( $_.Exception.Message.Contains("already exists") ) { # Class member already exists, so eat the error. $script:DataGroup = $Class; continue; } } (Get-F5.iControl).LocalLBClass.create_string_class( (,$StringClass) ); $script:DataGroup = $Class; } #------------------------------------------------------------------------- function Get-F5.MetaDataClass() #------------------------------------------------------------------------- { $script:DataGroup; } #------------------------------------------------------------------------- function Get-F5.MetaData() #------------------------------------------------------------------------- { param( $Product = $null, $Type = $null, $Name = $null, $Key = $null, $Value = $null ); $Objs = @(); # Build list $StringClassA = (Get-F5.iControl).LocalLBClass.get_string_class( (,$script:Datagroup) ); $StringClass = $StringClassA[0]; $classname = $StringClass.name; $members = $StringClass.members; for($i=0; $i -lt $members.length; $i++) { $tokens = $members[$i].Split($Separator); if ( $tokens.Length -eq 5 ) { $oProd = $tokens[0]; $oType = $tokens[1]; $oName = $tokens[2]; $oKey = $tokens[3]; $oValue = $tokens[4]; $o = New-F5.DataObject -Product $oProd -Type $oType -Name $oName -Key $oKey -Value $oValue; $match = $true; # Process filter parameters if ( ($Product -ne $null) -and ($oProd -notlike $Product) ) { $match = $false; } if ( ($Type -ne $null) -and ($oType -notlike $Type ) ) { $match = $false; } if ( ($Name -ne $null) -and ($oName -notlike $Name ) ) { $match = $false; } if ( ($Key -ne $null) -and ($oKey -notlike $Key ) ) { $match = $false; } if ( ($Value -ne $null) -and ($oValue -notlike $Value ) ) { $match = $false; } if ( $match ) { $Objs += (,$o); } } } $Objs; } #------------------------------------------------------------------------- function Set-F5.MetaData() #------------------------------------------------------------------------- { param( $Product = $null, $Type = $null, $Name = $null, $Key = $null, $Value = $null ); if ( ($Product -eq $null) -or ($Type -eq $null) -or ($Name -eq $null) -or ($Key -eq $null) -or ($Value -eq $null) ) { Write-Host "Usage: Set-F5.MetaData -Product prod -Type type -Name name -Key key -Value value"; return; } $StringClass = New-Object -TypeName iControl.LocalLBClassStringClass; $StringClass.name = $script:Datagroup; $StringClass.members = ( ,"${Product}:${Type}:${Name}:${Key}:${Value}"); trap { if ( $_.Exception.Message.Contains("already exists") ) { # Class member already exists, so eat the error. continue; } } (Get-F5.iControl).LocalLBClass.add_string_class_member( (,$StringClass) ); } #------------------------------------------------------------------------- function Remove-F5.MetaData() #------------------------------------------------------------------------- { param($Product = $null, $Type = $null, $Name = $null, $Key = $null, $Value = $null); if ( ($Product -eq $null) -or ($Type -eq $null) -or ($Name -eq $null) -or ($Key -eq $null) -or ($Value -eq $null) ) { Write-Host "Usage: Remove-F5.MetaData -Product prod -Type type -Name name -Key key -Value value"; return; } $StringClass = New-Object -TypeName iControl.LocalLBClassStringClass; $StringClass.name = $script:Datagroup; $StringClass.members = ( ,"${Product}:${Type}:${Name}:${Key}:${Value}"); trap { if ( $_.Exception.Message.Contains("was not found") ) { # Class member doesn't exists, so eat the error. continue; } } (Get-F5.iControl).LocalLBClass.delete_string_class_member( (,$StringClass) ); }189Views0likes0Comments