perl
7 TopicsBIG-IP Configuration Conversion Scripts
Kirk Bauer, John Alam, and Pete White created a handful of perl and/or python scripts aimed at easing your migration from some of the “other guys” to BIG-IP.While they aren’t going to map every nook and cranny of the configurations to a BIG-IP feature, they will get you well along the way, taking out as much of the human error element as possible.Links to the codeshare articles below. Cisco ACE (perl) Cisco ACE via tmsh (perl) Cisco ACE (python) Cisco CSS (perl) Cisco CSS via tmsh (perl) Cisco CSM (perl) Citrix Netscaler (perl) Radware via tmsh (perl) Radware (python)1.6KViews1like13CommentsBIG-IQ Central Management API automation and programmability - BULK Discovery, Import and Re Import - Perl
Summary In conjunction with the announcement of BIG-IQ 5.0 we are excited to bring the field greater flexibility when centrally managing BIG-IP devices utilizing well defined workflows and the BIG-IQ iControl REST API. We understand that automation and programmability is becoming more the norm these days as the network is evolving into a software defined application aware environment. This article is an addendum to “BIG-IQ Central Management API automation and programmability – Python” and will demonstrate bulk device trust, discovery to populate resolver groups and import bigip configuration of many BIG-IP device as defined in a csv configuration file. This automation can be run as a standalone utilities that will run directly in the BIG-IQ shell for adding devices to inventory in a sequential yet automated fashion. API Reference Trust: https://'bigiq-ip'/mgmt/cm/global/tasks/device-trust Discovery: https://'bigiq-ip'/mgmt/cm/global/tasks/device-discovey Import: ADC - https://'bigiq-ip'/mgmt/cm/adc-core/tasks/declare-mgmt-authority Import: Firewall - https://'bigiq-ip'/mgmt/cm/firewall/tasks/declare-mgmt-authority Let’s get started – When using the BIG-IQ it is suggested to make a directory called scripts under /shared and securely copy this distribution into /shared/scripts/. Contents: ../config/bulk_discovery.csv ../src/perl/bulkDiscovery.pl ../src/perl/bulkReImport.pl Everything is predicated by a main loop which will invoke each task by calling supporting perl subroutines self-contained in the script. All rest calls, using curl (https://curl.haxx.se/), made are highlighted below. Establishment of device trust is completed in the main loop while the process of discovery and import configurations are completed in subroutine blocks within the script. #====================================================== # Main loop # Process trust, discovery, and imports #====================================================== for $bigip (@bigips) { my %postBodyHash = ("address"=>$bigiq, "userName"=>$user, "password"=>$pw,"clusterName"=>"", "useBigiqSync"=>"false", "name"=>"trust_$mip"); my $postBody = encode_json(\%postBodyHash); my $trustCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X POST -d \'$postBody\' https://localhost/mgmt/cm/global/tasks/device-trust"; if (discoverModules($bigiq, $machineId)) { if (importModules($bigiq)) { } } # upgrade the framework if nessasary if (handleFrameworkUpdade ($trustTask, $bigip)) { } } end of all devices #====================================================== # Discover specified modules. #====================================================== sub discoverModules { my %postBodyHash = ("moduleList" => \@moduleList, "status" => "STARTED"); # POST a new discovery task $postBodyHash{"deviceReference"}{"link"} = "cm/system/machineid-resolver/$machineId"; my $newDiscoverTaskCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X POST -d \'$postBodyJson\' \"https://localhost/mgmt/cm/global/tasks/device-discovery\""; } end of discoverModules #====================================================== # A subroutine for importing individual module. #====================================================== sub importModule { # POST a new import task $postBodyHash{"deviceReference"}{"link"} = "cm/system/machineid-resolver/$machineId"; my $postBody = encode_json(\%postBodyHash); my $newImportTaskCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X POST -d \'$postBodyJson\' \"$dmaUrl\""; # if we ecounter conflicts, we mark them to use BigIQ, patch the task back to started, and poll again if (($currentStep eq "PENDING_CONFLICTS") or ($currentStep eq "PENDING_CHILD_CONFLICTS")) if (resolveConflicts($mip, $module, $currentStep, $importSelfLink, @conflicts)) } # end of importModule #========================================================== # sub routine calling importModule to colocate all modules #========================================================== sub importModules { $ltmSuccess = importModule($mip, "ltm", "https://localhost/mgmt/cm/adc-core/tasks/declare-mgmt-authority", %postBodyHash); $asmSuccess = importModule($mip, "asm", "https://localhost/mgmt/cm/asm/tasks/declare-mgmt-authority", %postBodyHash); } And last but not least Re Import of BIGIP configuration objects for greater than one BIGIP device. This script can be run periodically based on Linux cron to ensure your device configurations managed by BIGIQ are up to date. On occasion other Element Management Systems could modify BIGIP object base and BIGIQ should be aware of these changes. If you refer to the below main loop, the discovery and import call's are the same. So two things actually happen that differs from inital bulk discovery and import. 1. Trust establishment is removed as it already contains mutaul certificate trust. 2. We test if the discovery and import tasks exists, if they do we can just PATCH discovery and import tasks to enforce a re import. That's about it. Refer to the code snippet below. #====================================================== # Main loop # Process Re Discovery, and Imports #====================================================== for $bigip (@bigips) { ## get the device properties my $deviceCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X GET https://localhost/mgmt/shared/resolver/device-groups/cm-bigip-allBigIpDevices/devices"; ## call disc routine using ip and machine id. if (discoverModules($bigiq, $machineId)) { ## call import routine using up and machine id. if (importModules($bigiq, $machineId)) } } } # end for devices Just to re iterate the above the discovery and import routines used for Re Import just PATCH the existing task created during inital discovery and import. Here are the PATCH requests. #====================================================== # Discover specified modules. #====================================================== sub discoverModules { ## get the discovery task based on the machineId my $findDiscoverTaskCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X GET \"https://localhost/mgmt/cm/global/tasks/device-discovery?\\\$filter=deviceReference/link+eq+\'*$machineId*\'+and+status+eq+\'FINISHED\'\""; ## If it exists PATCH the task if (defined $discoveryTask->{"items"}[0]) { # PATCH the existing discovery task my $discoveryTaskSelfLink = $discoveryTask->{"items"}[0]->{"selfLink"}; $postBodyJson = encode_json(\%postBodyHash); my $discoverCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X PATCH -d \'$postBodyJson\' $discoveryTaskSelfLink"; } #====================================================== # A subroutine for importing individual module. #====================================================== sub importModule { ## get import task based on the machineid my $findImportTaskCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X GET \"$dmaUrl?\\\$filter=deviceReference/link+eq+\'*$machineId*\'\""; ## If exists PATCH the task if (defined $findImportTask->{"items"}[0]) { # PATCH the existing import task $importTaskLink = $findImportTask->{"items"}[0]->{"selfLink"}; my $importCmd = "curl -s -k -u $bigiqCreds -H \"$contType\" -X PATCH -d \'$postBodyJson\' $importTaskLink"; } #======================================== # sub routine for calling importModule to collocate all modules. #======================================== sub importModules { $ltmSuccess = importModule($mip, $machineId, "ltm", "https://localhost/mgmt/cm/adc-core/tasks/declare-mgmt-authority", %postBodyHash); $asmSuccess = importModule($mip, machineId, "asm", "https://localhost/mgmt/cm/asm/tasks/declare-mgmt-authority", %postBodyHash); } If you are interested in this code for collaboration or solution, seach on key words "bigiq" "api" "python" or "perl" in code share section on dev central or here is the reference link: https://devcentral.f5.com/s/articles/big-iq-big-ip-rest-api-bulk-device-discovery-perl-972 We will also create a repository on github for easy accessability. Please visit us soon and often for periodic updates.1.3KViews0likes12CommentsHosting Sorry, Error, or Maintenance Pages on BIG-IP LTM with iRules
Note Whereas you can still customize your BIG-IP with perl-scripts and sorry pages in this way, F5 has made this far easier with iFiles, introduced in 11.1. This tech tip on iFiles should be the recommended path for sorry pages going forward. I’ve posted on this before (Host that Sorry Page on your BIG-IP!) but it’s been a while and there have been a few updates. Besides, narrowing the application to only sorry pages is a bit myopic—I’m sure my BIG-IP is offended that I treated it so callously. Anyway, I got an inquiry a week or so ago about the images in tables not being picked up by the script. The images in the table were referenced as such: #<table background="genericofflinebackground.gif" align="center" width="1024" height="768" > I reached out to the author, Kirk Bauer, and he gave me some pointers as where to look. There’s a function in the perl script that parses the html to look for items of interest: sub start { my ($self, $tag, $attr, $attrseq, $origtext) = @_; # print out original text if ($tag eq 'img') { if ($attr->{'src'}) { $attr->{'src'} = &handle_object($tag, 'src', $attr->{'src'}); } } Modifying the if ($tag..) conditional to match the table wasn’t that hard at all: sub start { my ($self, $tag, $attr, $attrseq, $origtext) = @_; # print out original text if ($tag eq 'img') { if ($attr->{'src'}) { $attr->{'src'} = &handle_object($tag, 'src', $attr->{'src'}); } } if ($tag eq 'table') { if ($attr->{'background'}) { $attr->{'background'} = &handle_object($tag, 'background', $attr->{'background'}); } } That solved problem number one. The second problem with the script was that it wasn’t asking about partition preference, rather it just dumped the iRule and datagroups into the last partition defined in bigip.conf. This was strange, as the code to handle partitions was in place: my @partitions; open (CONF, "/config/bigip.conf") or die "Could not read /config/bigip.conf: $!\n"; while (my $line = <CONF>) { if ($line =~ /^partition (.+) {/) { push @partitions, $1; } } The problem is that the regex is trying to match “partition <my partition> {“ and that is (at least in 10.2.1 HF3) no longer in the bigip.conf file. It has been moved to bigip_sys.conf. Updating the code as shown below solved the issue and now the user is asked for the appropriate partition and the iRule and datagroup gets deployed as expected. my @partitions; open (CONF, "/config/bigip_sys.conf") or die "Could not read /config/bigip_sys.conf: $!\n"; while (my $line = <CONF>) { if ($line =~ /^partition (.+) {/) { push @partitions, $1; } } For the full script, head to the iRules wiki entry LTM Maintenance Page Generator and grab version 2.2. Related Articles Host that Sorry Page on your BIG-IP! about i-rule sorry page configuration - DevCentral - F5 DevCentral ... DevCentral Wiki: Automatic_maintenance_page___ Sorry_page_with_images DevCentral Wiki: Sorry Page I Rule Generator_ Perl DevCentral Wiki: LTM Maintenance Page Generator DevCentral Wiki: CodeShare Sorry Page when Severs are down - DevCentral - F5 DevCentral ... Site Dwon Page form https virtual server - DevCentral - F5 ...818Views0likes3CommentsForcing a reload of External Data Groups within an iRule
This article shows how to use iControl to force an iRule to reload external configuration data when that data has changed. Background One of the more common uses of iRules is to extract part of the request (client-ip, host, uri, payload, ...) and use that as input to a policy making decision. Most often, the data you are comparing your input to (a list of blacklisted ip addresses, a list of valid hosts, uri to server mappings, etc) is too long to store directly within an iRule. Data Groups That's where Data Groups come in. Data Groups (or classes) are simply lists that can be references at the global scope from within an iRule to make the iRule itself more manageable. You can use the matchclass and findclass helper commands to lookup values in Data Groups or you could use the TCL list commands to loop through the list manually. There are four types of data groups: Address, String, Integer, and External. Address Data Groups are used to store a list of IP Addresses (and optionally subnet masks). These are often used when comparing an incoming client address against a list of valid or invalid addresses. String Data Groups store a list newline delimited strings. These are multi-purpose as you can use them for straight lookups (valid requested uri or hostname) or for building mapping (this uri gets routed to that pool). Given a token delimiter, the findclass command can be used to look for the first token in the string and return the second token. Integer Data Groups store a list of integers. A common use for this type of data group is to compare an ID passed in as part of the URI to a valid value. While this could be accomplished with a string data group, integer data groups require less resources and comparisons are faster. External Data Groups are lists that are stored externally the data base (on the file system). These can be of any of the other three types (Address, String, and Integer). A common use for this type of Data Group is when you are storing thousands of values and those values change often. It is much easier to manage an external file via a text editor, or a remote API like iControl. The Problem The iRules engine utilizes a caching mechanism for external Data Groups. The problem is that when a change is made to an External Data Group, The iRules engine has no way of knowning that the changes have actually been made. Even a configuration reload will not do it as a reload is just an overwrite on the current configuration and since the iRule didnt' change the internal caching doesn't get invalidated and the next time the iRule is processed it still reads the cached values in the Data Group. The Solution Fear not, there is a fairly simple solution. If you invalidate the iRule itself by changing it, the cache will be invalidated and the External Data Group will be reloaded. How do you do this? Well, we've found that the easiest way is to add a space to the end of the iRule. This will not change the behaviour of the iRule but will cause it's checksum to change. Just add a space to the end, save the iRule, then delete the space, and then save the iRule again! This can be accomplished via the GUI, CLI, or iControl. The GUI and CLI are fiarly intuitive, so I'll show you how to use iControl to do this. More than likely for large External Data Groups, you are using iControl already to remotely add/remove items from the lists. If that is the case, it is a very simple addition to your application to add this logic. If you are not using iControl to manage your External Data Group, then you can plop this perl script right on your BIG-IP and use it from the command line. Either way, we've got you covered. Here's an iControl application written in Perl that will invalidate an iRule to force reloading of Data Groups. #!/usr/bin/perl #---------------------------------------------------------------------------- # 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-2006 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. #---------------------------------------------------------------------------- #use SOAP::Lite + trace => qw(method debug); use SOAP::Lite; #---------------------------------------------------------------------------- # Variables #---------------------------------------------------------------------------- my $DEBUG = 0; my $sHost = "localhost"; my $sPort = 80; my $sUID = ""; my $sPWD = ""; my $sProtocol = "http"; my $sRuleName = "MSM_reputation"; #---------------------------------------------------------------------------- # Transport Information #---------------------------------------------------------------------------- sub SOAP::Transport::HTTP::Client::get_basic_credentials { return "$sUID" => "$sPWD"; } #---------------------------------------------------------------------------- # iControl interface declarations #---------------------------------------------------------------------------- $LocalLBRule = SOAP::Lite -> uri('urn:iControl:LocalLB/Rule') -> readable(1) -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi"); #---------------------------------------------------------------------------- # Main logic #---------------------------------------------------------------------------- &invalidateRule(); #---------------------------------------------------------------------------- # sub invalidateRule # # This iRule will query the contents of an iRule, save it with an added space # and then re-save it with the original contents. #---------------------------------------------------------------------------- sub invalidateRule() { if ( $DEBUG ) { print "Querying rule definition for rule '$sRuleName'\n"; } # Query the rule definition $soapResponse = $LocalLBRule->query_rule(SOAP::Data->name(rule_names => [$sRuleName])); &checkResponse($soapResponse); @RuleDefinitionList = @{$soapResponse->result}; # Extract the first element in the array $RuleDefinition = @RuleDefinitionList[0]; # save the original and temporary changed values $rule_definition = $RuleDefinition->{"rule_definition"}; $temp_rule_definition = "$rule_definition "; # update RuleDefinition with the temporary rule details if ( $DEBUG ) { print "modifying with temporary changes...\n"; } $RuleDefinition->{"rule_definition"} = $temp_rule_definition; $soapResponse = $LocalLBRule->modify_rule(SOAP::Data->name(rules => [$RuleDefinition])); &checkResponse($soapResponse); # update RuleDefinition with the original rule details. if ( $DEBUG ) { print "modifying with reverted changes...\n"; } $RuleDefinition->{"rule_definition"} = $rule_definition; $soapResponse = $LocalLBRule->modify_rule(SOAP::Data->name(rules => [$RuleDefinition])); &checkResponse($soapResponse); if ( $DEBUG ) { print "rule initialized...\n"; } } #---------------------------------------------------------------------------- # sub checkResponse # Exit on SOAP Fault. #---------------------------------------------------------------------------- sub checkResponse() { my ($soapResponse) = (@_); if ( $soapResponse->fault ) { print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n"; exit(); } }811Views0likes8CommentsGeneration of Utility Billing Report using BIG-IQ's API
This script generate the utility billing report based of a list of regKey.This script only applies to utility-type licenses used for F5's subscription and/or ELA programs. The regkey listed in the csv file or in the command line are the registration key associated with the license pool you wish to report on. Reports can be automatically submitted to F5 or manually created. /!\ This feature will be included with BIG-IQ 6.1 /!\ Automatic report submission requires BIG-IQ to access api.f5.com. BIG-IQ makes a REST call over SSL to api.f5.com to upload the report. Manual report submission is used in cases where BIG-IQ cannot reach api.f5.com. In this workflow, the customer generates the report, extracts it, then emails it to F5 (/shared/scripts/F5_Billing_License_Report.<date>.json). Pre-Requisist: Make sure you can access api.f5.com port 443 if automatic reporting is chosen (nslookup api.f5.com, ping api.f5.com, telnet api.f5.com 443). The script has to be executed locally from the BIG-IQ. Installation: The script mustbe installed in BIG-IQ under /shared/scripts: # mkdir /shared/scripts # chmod +x /shared/scripts/licenseUtilityReport.pl Allowed command line options: -h Help -c Path to CSV file with all regKey - REQUIRED if not using -k -k regKey(s) separated by , - REQUIRED if not using -c -r Report option automatic or manual - OPTIONAL (default is automatic) Command example automatic report: # cd /shared/scripts # ./licenseUtilityReport.pl -k DRLPZ-JISKU-VPUPT-HZMMV-LERVPYQ,GYCWI-FOUEZ-YMWPX-LYROB-PXTKMTG CSV file example manual report: # ./licenseUtilityReport.pl -c listregkey.csv-r manual # cat listregkey.csv DRLPZ-JISKU-VPUPT-HZMMV-LERVPYQ GYCWI-FOUEZ-YMWPX-LYROB-PXTKMTG Cron table example (every 1st of the month at 10am) for both above examples: # crontab -e (edit: type 'o' to add a new line, then 'ESC' and ':x' to save and quit) # crontab -l (list) 0 10 1 * * /usr/bin/perl /shared/scripts/licenseUtilityReport.pl -k DRLPZ-JISKU-VPUPT-HZMMV-LERVPYQ 0 10 1 * * /usr/bin/perl /shared/scripts/licenseUtilityReport.pl -c /shared/script/listregkey.csv-r manual ┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday; │ │ │ │ │ 7 is also Sunday on some systems) │ │ │ │ │ │ │ │ │ │ ** * * * In case you need toobfuscate the Utility Billing Report before sending it, use manual export, then use the following script to mask IP/Macaddresses and Hostnames from the report. Then submit/email report to F5 (Please contact F5 Support for assistance). # ./f5_sanitize_usage_report.sh F5_Billing_License_Report.<date>.json Location of the scriptson GitHub:https://github.com/f5devcentral/f5-big-iq-pm-team550Views0likes0Comments64-bit numbers in perl
A question recently came up in the iControl forums about how to deal with the statistics returned by our iControl interfaces. In 9.0, we changed the interfaces to return true 64-bit values consisting of a structure of a low and high 32-bit value (this is due to the fact that there is a lack of support in the SOAP encoding specs, and some of the languages, for native 64-bit numbers). Our SDK samples show something like this: $low = $stat->{"low"}; $high = $stat->{"high"}; $value64 = ($high<<32)|$low; The question was asked, how come the value is truncated to a 32-bit number? I asked myself that same question as it worked for my build. After some digging, it turns out that perl needs to be compiled specifically to allow include support for 64-bit numbers. You can check your installation out by using the Config module use Config; ($Config{use64bitint} eq 'define' || $Config{longsize} >= 8) && print "Supports 64-bit numbers\n"; So, what do you do if you don't have control to rebuild your version of perl? Well, thanks to a user who pointed me this way, there exists a perl module to support large numbers. As long as you have the Math::BigInt package installed, you can use it as follows: use Math::BigInt; $low = $stat->{"low"}; $high = $stat->{"high"}; $value64 = Math::BigInt->new($high)->blsft(32)->bxor($low); Happy Coding! -Joe456Views0likes1CommentDevCentral Top5 04/14/2012
Given the time and my unabashed geekery for all things comic related, especially Batman-esque, I feel the burning need to make some sort of "Dark Knight" joke here, but I'll refrain. That kind of thing would drive readers batty, and I just don't have any desire to come off as a Joker. Here's where you groan...all together now. All right, now that that's out of my system...we've got lots of goodness to get to. The ninjas and pirates (we're diverse like that) that keep things running out in DevCentral land have been hard at work putting together a host of content that shouldn't be missed. Let's get right to it with my Top5 picks for the week: 1024 Words: 1000 Posts https://devcentral.f5.com/s/weblogs/macvittie/archive/2012/04/11/1024-words-1000-posts.aspx First and foremost, I'd like to take a moment to congratulate a truly prolific contributor to DevCentral. Lori MacVittie has reached the 1000 blog post mark on DevCentral, and to me, that is definitely Top5 worthy. She blew past that number, in fact, but this is the first chance I've had to call it out. Not only is this a DC first, and momentous for that reason, but it's also a showing of a truly massive outpouring of content to continue engaging and bettering the community. Ironically her post is most a big thank you to her readers (spoiler alert...wait, I think I did that wrong), and I want to thank her here...but I can handle a little irony from time to time. Go take a look, browse through some of her old posts, and drop a thank you from all of us to her for doing what she does. iControl Guru Panel - A "Pi" Day Webcast With iControl Gurus https://devcentral.f5.com/s/weblogs/dctv/archive/2012/03/14/icontrol-guru-panel-a-quotpiquot-day-webcast-with-icontrol.aspx I've been remiss in mentioning the Guru panels that we've done on DevCentral! So swept up with the other content was I that I forgot to call out this cool new thing that is happening on an internet near you. Available now is the growing series of Guru Panels that we here on the DC team have been cooking up. It started way back when with the iApp Guru panel, then came iRules, and most recently iControl. So what is a Guru panel you ask? A guru panel is where we get together a couple of experts on a given topic, sit down in front of a camera, have a dialog, and ask the community to feed us questions to answer. What usually comes out is a lively discussion that ranges from the kiddy pool with water wings to a half gainer from the high dive, with plenty of history, commentary and anecdotes along the way. These are a great way to get an infusion of knowledge about a particular subject, or to see what the community is up to and curious about. Whatever your reason, they're informational, low key and fully community driven. That's a good combo any way you slice it. Take a look and keep an eye out for future Guru panels. I know there's a security one right around the corner, so keep a sharp watch for more info. Perl example of deploying an iApp application service https://devcentral.f5.com/s/wiki/iControl.Perl-example-of-deploying-an-iApp-application-service.ashx I don't often call out specific CodeShare entries here in the Top5. That's not because there aren't awesome things being added to the CodeShare all the time (hint: there are), it's more because there is usually just so much stuff to go through I can't even get to it all. This week, however, one of the engineers here in one of F5's Skunk Works style teams swung by my desk to ask where to post a particular code sample. He wanted to post an example written in Perl, using iControl, to deploy an iApp. I'm going to repeat that, because that is the kind of thing that bears repeating. Perl -> iControl -> iApp. That's like...a trifecta. If he had told me the iApp was then used to deploy or manage iRules, I think I may have shed a tear of joy and built a shrine in reverence. Regardless, this is a pretty wicked example of combining F5 technologies and making them work for you in an automated fashion. It also happens to touch on some of my favorite bits in the system, which may or may not have played partially into my decision to include this post here. Perhaps. Possibly. It's cool, I promise! Check it out and be impressed, I was. Freedom vs. Control https://devcentral.f5.com/s/weblogs/psilva/archive/2012/04/11/freedom-vs.-control.aspx Pete Silva delivers an interesting read this week in the form of a dilemma of sorts: Freedom vs. Control. We're not talking about political power struggles here, we're talking about corporate security policies and how they are in a pinch when trying to deliver the right balance of both. With an increase in mobile devices, the BYOD trend continuing to rise, and the proliferation of platforms outside of IT's direct control, it would seem that confidence is waning in regards to which devices are actually accessing business resources. If many companies can't even be sure of which devices are accessing apps, then how are they going to balance their security measures appropriately? It's a bit of a vexing question to be sure, and Pete digs into a bit more in this post. Take a look and see what you think. Your guess is as good as mine on this one, but it's definitely something to be thinking about, and the sooner the better, especially for those of you that may be responsible for implementing or tuning such policies. Stripping EXIF From Images as a Security Measure https://devcentral.f5.com/s/weblogs/macvittie/archive/2012/04/09/stripping-exif-from-images-as-a-security-measure.aspx Do you know what an Exif tag is? Let me save you the trouble, here's what Wikipedia will tell you: "Exchangeable image file format (Exif) is a standard that specifies the formats for images, sound, and ancillary tags used by digital cameras (including smartphones), scanners and other systems handling image and sound files recorded by digital cameras." So what does that mean, and why is that a security risk? Well, digging a little deeper you'll quickly find out that one of the tags included in the Exif info of many pictures these days stores geolocation data. Why do you care about geolocation info on your photos? Well, what about the photos you're taking of your house, car, personal jet-pack or other such sundry goods with your GPS enabled smart phone that all now have the exact GPS coordinates of where said images were taken embedded in them? Those photos you posted to that everyone on the tubes can now see detailing the amazing new widget you bought? Yeah, it also might contain the exact location of said widget, for someone who is looking deep enough. Does this sound like a security issue to you yet? It does to me. Lori digs into it in a lot more detail and depicts a possible solution in this post. This is becoming massively prevalent and could be a serious concern in some cases...this one is definitely worth the time to read. There you have it my intrepid friends, another 5 goodies from the DevCentral realm to tide you over until next time. Enjoy! #Colin P.S. This may be the first Top5 in history without an iRules specific post. P.P.S. Don't count on that becoming a trend. I haven't given up the faith.175Views0likes0Comments