Using bash and tmsh to make bulk updates
Lessons learned while writing K000149084
How this began
Customers who may have had AAM/WAM enabled in their BIG-IP systems may be unaware of removal of that entire module and code branch that was done in versions 16 and above. Any BIG-IP systems that had these objects configured, would face problems when upgrading their devices, unless they cleaned the configuration up.
Since there are many different types of objects (TCP Profiles, Web acceleration Profiles, Acceleration Manager applications, etc), and since iApps were likely the primary deployment method to use AAM/WAM features, I wanted to find a fast way to document and make the changes needed for anyone impacted.
Prerequisites
- Access to your BIG-IP system via your preferred SSH client.
- Admin credentials for the BIG-IP system.
- Access to the Advanced Shell, aka BASH.
Finding specific profiles and settings via the GUI would be rather time consuming, and there is no good way to catalog and inventory what needs to be changed via the GUI. While we can list some items via tmsh, there are better filtering and output formatting tools within bash, plus we can more easily traverse all partitions on the system. I will explain as much about the commands as I know or have discovered in this process. If you consider yourself a bit more advanced, then just skip to the code blocks and enjoy.
Before taking any of this to a BIG-IP, ensure that you have backed up the configuration and pulled that UCS file off the device. ALWAYS experiment on a test/non production environment before running any of these commands that have modify or delete statements in them.
Scanning All Partitions
When you launch into tmsh, by default, users with admin permissions will enter into the Common partition. To scan all partitions, you have to get to the root in tmsh. Like most shells, cd / will put you in the root directory. From there, we can use the list command with the recursive option to return objects of interest from all partitions and subfolders (iApps and FAST create subfolders within a partition). Filtering for values of interest and then acting on them is a critical step to ensure we have a proper list for editing later.
A challenge to solve is that we need to send two commands into tmsh to get all of the objects across all partitions. Fortunately, tmsh has an option that allows us to send multiple commands via the -c option. The multiple commands need to be inside quotes and separated by a semi-colon.
List all Virtual Servers on a device
#this will return a list of all virtual server names
tmsh -c 'cd /; list ltm virtual recursive one-line' | awk '{print $3}'
Without the awk command, the entire virtual server config will be returned. In this example, awk is returning the third string/column it sees surrounded by spaces. Because we have every virtual server config, we can search for specific elements of interest using grep to either include or exclude based on what we seek.
List all Virtual Servers on a device using the tcp profile
Before you build a fancy grep string, only to figure out the value is not returned by the command because it is an implicit default value, add the all-properties option before the one-line option. In this example, we will list all virtual servers where the default tcp profile is being used for client-side (downstream in NGINX) and server side (upstream in NGINX).
#Find Virtual Servers using the default tcp profile on client side and server side
tmsh -c 'cd /; list ltm virtual recursive all-properties one-line' | grep -E "Common/tcp { context all }" |awk '{print "/" $3}'
With this command, you have the names of all virtual servers that have this setting and can use that for your change management documentation. There is a slight change in the output of this command, where we have awk add a slash to the object name. When referencing an object in a tmsh command, it can either be just the name of the object if you are in the partition OR you give the full partition name to the command. In some cases where tmsh does not see the partition syntax, it will explicitly insert /Common onto the virtual server name and will fail.
Now you may notice some virtual server names are much longer and you may see a. app somewhere in the name. That means you have virtual servers that were deployed using iApps. For making batch updates, as we will here, iApps by default, will block attempts to make changes.
List iApps with Strict Updates enabled (default value)
#show deployed iApps that have strict-updates enabled
#Because this is a default setting, we have to look at all-properties.
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -E "strict-updates enabled" | awk '{ print "/" $4 }'
While we tend to shorthand the objects as iApps, the config calls them an application service and they are stored in the system module versus the ltm module.
List iApps with Strict Updates disabled
If you want to find the iApp names where Strict Updates are disabled, you can change the grep string to find "strict-updates disabled" or you can add a -v to the previous grep command.
#show deployed iApps that have strict-updates disabled method 1
#While we do not need the all-properties option, we will keep it for consistency.
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -E "strict-updates disabled" | awk '{ print "/" $4 }'
#show deployed iApps that have strict-updates disabled method 2
#While we do not need the all-properties option, we will keep it for consistency.
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -v "strict-updates enabled" | awk '{ print "/" $4 }'
List iApps with Strict Updates enabled for Virtual Servers with default tcp profile in client and server contexts
Before we make changes to the iApps, we usually want to be very selective in what we select for changes. Due to the location of the two values, the tcp profile in the virtual server, and the strict updates iApp setting, we will use a bash variable to build the search string argument. Because we are only looking for virtual servers built by an iApp, we have to exclude virtual servers that do not have an app-service defined. This is accomplished with the -v option for grep. Next, we have to format the output for a grep friendly OR expression. In this case, we replace the new line character with a pipe character using tr and then we use sed to remove the last pipe character that tr put into the string.
Note that if the command that feeds inScopeiApp returns nothing, then the final tmsh command will have a grep error when it tries to parse a null (empty) string.
#List the iApps that are in scope and will interfere with the commands
#due to app-service none being an implicit default, we must use the all-properties directive to list it in the output.
#due to strict-updates being enabled by default, we must use the all-properties directive to list it in the output.
inScopeiApp=$(tmsh -c 'cd /; list ltm virtual recursive one-line all-properties' | grep -E "Common/tcp { context all }" | grep -v "app-service none" | awk '{print $10 }' | tr '\n' '|' | sed '$s/.$/\n/')
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -E "strict-updates enabled" | awk '{ print "/" $4 }' | grep -E $inScopeiApp
List iApps with Strict Updates enabled for Virtual Servers with AAM/WAM based profiles
Now we are getting a bit more complex and have to go a level deeper to find the defaults-from values of profiles as well as some known profile names. First we build the PROFILES string with the known profile names, and then add in the profile names that have inherited an AAM/WAM profile. Then we get virtual server names that use those profiles to determine the list of iApps that we want to see if we need to disable strict-updates.
#List the iApps that are in scope and will interfere with the commands
#due to strict-updates being enabled by default, we must use the all-properties directive to list it in the output.
PROFILES="wam-tcp-lan-optimized|wam-tcp-wan-optimized|wom-tcp-lan-optimized|wom-tcp-wan-optimized|"$(tmsh -c 'cd /; list ltm profile recursive one-line' | grep -E "defaults-from.*(wam|wom|webacceleration)" | awk '{print $4}' | tr '\n' '|' | sed '$s/.$/\n/')
inScopeiApp=$(tmsh -c 'cd /; list ltm virtual recursive one-line all-properties' | grep -E "(profiles.*($PROFILES))" | grep -v "app-service none" | awk '{print $10 }' | tr '\n' '|' | sed '$s/.$/\n/')
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -E "strict-updates enabled" | awk '{ print "/" $4 }' | grep -E $inScopeiApp
Using the lists to make changes
Everything we have done so far is to find objects of interest to document them for future changes/deletions, etc. Now we will take these lists as input for modifying statements. The tool I chose was xargs because it can write and execute commands based on the inputs you give it.
Changing the Strict Updates setting in iApps to allow out of band modifications
It is important to note that while you may loosen this setting to make this change and then set it again, these steps are out of band modifications to the iApp, and as a result, you may never use the Reconfigure GUI nor update the iApp template. Of note, iApps are now deprecated in favor of FAST for AS3. You can read more on that here—https://my.f5.com/manage/s/article/K13422
This example is lifted from K000149084, to find all iApps that use profiles associated with AAM/WAM and disable strict updates. I chose to add the -T option to xargs, so that it would output the commands it was running. This way if there is an error or you need to record what was done, you will have a record of it.
#Modify the iApps that are in scope and will interfere with the commands
#due to strict-updates being enabled by default, we must use the all-properties directive to list it in the output.
#***IMPORTANT NOTE - This script aims to specifically target ONLY the iApps needed for the steps below to succeed.
#Once Strict updates are disabled and changes made to the objects, you can no longer update the template or use the Reconfigure screen in the GUI.
PROFILES="wam-tcp-lan-optimized|wam-tcp-wan-optimized|wom-tcp-lan-optimized|wom-tcp-wan-optimized|"$(tmsh -c 'cd /; list ltm profile recursive one-line' | grep -E "defaults-from.*(wam|wom|webacceleration)" | awk '{print $4}' | tr '\n' '|' | sed '$s/.$/\n/')
inScopeiApp=$(tmsh -c 'cd /; list ltm virtual recursive one-line all-properties' | grep -E "(profiles.*($PROFILES))" | grep -v "app-service none" | awk '{print $10 }' | tr '\n' '|' | sed '$s/.$/\n/')
tmsh -c 'cd /; list sys application service recursive one-line all-properties' | grep -E "strict-updates enabled" | awk '{ print "/" $4 }' | grep -E $inScopeiApp | xargs -t -I iAppname tmsh modify sys application service iAppname strict-updates disabled
Changing Parent Profiles for TCP profiles that have AAM/WAM based profiles
In the last list segment, you were introduced to the code where we scan for known tcp profiles and then a list of profiles that inherited their settings from an AAM/WAM profile. Now we will just look for tcp profiles that inherited their settings from an AAM/WAM profile and change them to use Optimized TCP profiles. Because this is a new iteration, I will show the list of commands separately, for the change management side of things to identify the profiles and the virtual servers that would be impacted.
#Find TCP profiles with wam/wom based profiles
tmsh -c 'cd /; list ltm profile tcp recursive one-line' | grep -E "defaults-from.Common.w(a|o)m-tcp-*" | awk '{ print "/" $4 }'
#List the virtuals with any profiles that are related to WAM/WOM/AAM
PROFILES="wam-tcp-lan-optimized|wam-tcp-wan-optimized|wom-tcp-lan-optimized|wom-tcp-wan-optimized|"$(tmsh -c 'cd /; list ltm profile recursive one-line' | grep -E "defaults-from.*(wam|wom|webacceleration)" | awk '{print $4}' | tr '\n' '|' | sed '$s/.$/\n/')
tmsh -c 'cd /; list ltm virtual recursive one-line' | grep -E "(profiles.*($PROFILES))" | awk '{print "/" $3}'
Due to the requirements of wan side and lan side, the commands are very specific to each context.
When updating a virtual server, you have to first add the new profiles and then delete the unwanted ones. When you attempt to delete the profiles first, the system will give you an error as it is a mandatory field.
*** Note these commands will fail on objects that are a part of an iApp that has strict enabled
#**************************************************************************************************************
#These commands will change your configuration, so only use when ready #Find TCP profiles with wam/wom based profiles for lan and replace the defaults-from
tmsh -c 'cd /; list ltm profile tcp recursive one-line' | grep -E "defaults-from.Common.w(a|o)m-tcp-lan*" | awk '{ print "/" $4 }' | xargs -t -I tcp_profile tmsh modify ltm profile tcp tcp_profile defaults-from f5-tcp-lan
#Find TCP profiles with wam/wom based profiles for wan and replace the defaults-from
tmsh -c 'cd /; list ltm profile tcp recursive one-line' | grep -E "defaults-from.Common.w(a|o)m-tcp-wan*" | awk '{ print "/" $4 }' | xargs -t -I tcp_profile tmsh modify ltm profile tcp tcp_profile defaults-from f5-tcp-wan
#Execute commands for TCP profile updates to the Virtual Servers in all partitons. have to do this in a server side and client side pass to avoid errors
tmsh -c 'cd /; list ltm virtual recursive one-line' | grep -E "(profiles.*(w(a|o)m-tcp-lan*))" | awk '{print "/" $3}' | xargs -t -I vsName tmsh modify ltm virtual vsName profiles add { f5-tcp-lan { context serverside } } profiles delete { wam-tcp-lan-optimized }
tmsh -c 'cd /; list ltm virtual recursive one-line' | grep -E "(profiles.*(w(a|o)m-tcp-wan*))" | awk '{print "/" $3}' | xargs -t -I vsName tmsh modify ltm virtual vsName profiles add { f5-tcp-wan { context clientside } } profiles delete { wam-tcp-wan-optimized }
Changing the default TCP profile on Virtual Servers to use Optimized TCP Profiles
In case you did read Martin Duke's posts about using the base tcp profile Stop Using the Base TCP Profile! or you saw F5 Unveils New Built-In TCP Profiles or you noticed what was used in the new FAST HTTP Template, and want to go all in, well here is the command to change any virtual server that you found in the second example, to use the Optimized TCP Profiles. Unlike our previous tcp profile modification, we can do this in one pass because the Serverside inherited the setting from the Clientside.
#Execute commands for TCP profile updates to the Virtual Servers in all partitons.
#We have to add the profiles before we can delete the one we want to remove.do this in a server side and client side pass to avoid errors
tmsh -c 'cd /; list ltm virtual recursive one-line all-properties' | grep -E "Common/tcp { context all }" | awk '{print "/" $3}' | xargs -t -I vsName tmsh modify ltm virtual vsName profiles add { f5-tcp-lan { context serverside } } profiles add { f5-tcp-wan { context clientside } } profiles delete { tcp }
Conclusion
With these commands, you have gained an understanding of how to look for certain settings and then make the changes you would like.