Perl Add iRule To All Virtuals

Problem this snippet solves:

This iControl application illustrates how to mass-deploy an iRule to all of the virtual servers on the system.

How to use this snippet:

Syntax

$ ./AddiRuleToAllVirtuals.pl 10.10.10.1 username password ./MyiRuleFile.tcl add

$ ./AddiRuleToAllVirtuals.pl 10.10.10.1 username password ./MyiRuleFile.tcl remove

Caveats

This iControl app is setup to continue on errors when performing actions to add or remove iRules from the virtual servers. It will print out summaries for successes and failures. There are situations where a certain type of iRule (say one that has HTTP commands) will not be able to be attached to a virtual server unless the appropriate profiles are associated with it (for instance HTTP or FASTHTTP).

Code :

#!/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-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.
#----------------------------------------------------------------------------

#use SOAP::Lite + trace => qw(method debug);
use SOAP::Lite;
use File::Basename;

# Bypass self signed certificate error
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;

#----------------------------------------------------------------------------
# Validate Arguments
#----------------------------------------------------------------------------
my $sHost = $ARGV[0];
my $sUID = $ARGV[1];
my $sPWD = $ARGV[2];
my $sRule = $ARGV[3];
my $sCmd = $ARGV[4];

if ( "" eq $sCmd ) { $sCmd = "add"; }

#============================================================================
sub usage()
#============================================================================
{
print "Usage: AddiRuleToAllVirtuals.pl host uid pwd rule_file \n";
  exit;
}

if ( ($sHost eq "") or ($sUID eq "") or ($sPWD eq "") or ($sRule eq "") )
{
usage();
}


#----------------------------------------------------------------------------
# Transport Information
#----------------------------------------------------------------------------
sub SOAP::Transport::HTTP::Client::get_basic_credentials
{
return "$sUID" => "$sPWD";
}

$LocalLBRule = SOAP::Lite
-> uri('urn:iControl:LocalLB/Rule')
-> readable(1)
-> proxy("https://$sHost/iControl/iControlPortal.cgi");

$LocalLBVirtualServer = SOAP::Lite
-> uri('urn:iControl:LocalLB/VirtualServer')
-> readable(1)
-> proxy("https://$sHost/iControl/iControlPortal.cgi");

eval { $LocalLBRule->transport->http_request->header
(
'Authorization' =>
'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')
); };

eval { $LocalLBVirtualServer->transport->http_request->header
(
'Authorization' =>
'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')
); };


#============================================================================
sub getiRuleName()
#============================================================================
{
my($file) = (@_);
my $basename = &basename($file);
my ($rule_name, $ext) = split(/\./, $basename, 2);
return $rule_name;
}

#============================================================================
sub createiRule()
#============================================================================
{
  my($file) = (@_);
  my $file_data;
  my $chunk_size = 64*1024;
  open(LOCAL_FILE, "<$file") or die("Can't open $localFile for input: $!");
  $bytes_read = read(LOCAL_FILE, $file_data, $chunk_size);
  close(LOCAL_FILE);
  
  my $rule_name = &getiRuleName($file);
  
  #$rule_name = &basename($file);
  #$rule_name =~ s/.tcl$//g;
  
  print "iRule Data\n";
  print $file_data;
  print "\n";
    
  $iRuleDefinition = {
    rule_name => $rule_name,
    rule_definition => $file_data
  };
  
  my $exists = &doesiRuleExist($rule_name);
  if ( $exists )
  {
    # Modify existing iRule
    $soapResponse = $LocalLBRule->modify_rule(
      SOAP::Data->name(rules => [$iRuleDefinition])
    );
    &checkResponse($soapResponse);
    print "iRule $iRuleName successfully updated\n";
  }
  else
  {
    # Create new iRule
    $soapResponse = $LocalLBRule->create(
      SOAP::Data->name(rules => [$iRuleDefinition])
    );
    &checkResponse($soapResponse);
    print "iRule $iRuleName successfully created\n";
  }
}

#============================================================================
sub removeiRule()
#============================================================================
{
my ($file) = (@_);

my $rule_name = &getiRuleName($file);

print "Removing Rule '$rule_name': ";
$soapResponse = $LocalLBRule->delete_rule(
SOAP::Data->name(rule_names => [$rule_name])
);
$success = &checkResponse($soapResponse, 1);
print $success ? "SUCCEEDED\n" : "FAILED\n";
}

#============================================================================
sub getVirtualServerList()
#============================================================================
{
$soapResponse = $LocalLBVirtualServer->get_list();
&checkResponse($soapResponse);
@vs_list = @{$soapResponse->result};
return @vs_list;
}  

#============================================================================
sub doesiRuleExist()
#============================================================================
{
  my($name) = (@_);
  my $exists = 0;
  
  if ( ! $name eq "" )
  {
    my @RuleDefinitionList = &getiRuleDefinitions($name);
    foreach $RuleDefinition (@RuleDefinitionList)
    {
      $rule_name = $RuleDefinition->{"rule_name"};
      if ( $rule_name eq $name )
      {
        $exists = 1;
        break;
      }
    }
  }
  return $exists;
}  

#============================================================================
sub getiRuleDefinitions()
#============================================================================
{
  my($rulename) = (@_);
  if ( $rulename eq "" )
  {
    $soapResponse = $LocalLBRule->query_all_rules(); 
    &checkResponse($soapResponse);
    @RuleDefinitionList = @{$soapResponse->result};
    return @RuleDefinitionList;
  }
  else
  {
    $soapResponse = $LocalLBRule->query_rule(
      SOAP::Data->name(rule_names => [$rulename])
    );
    &checkResponse($soapResponse, 1);
    @RuleDefinitionList = @{$soapResponse->result};
    $RuleDefinition = @RuleDefinitionList[0];
    return $RuleDefinition;
  }
}

#============================================================================
sub deployMitigation()
#============================================================================
{
my ($file) = (@_);

# Read in and create/update the iRule
&createiRule($file);

  my $rule_name = &getiRuleName($file);
  my $priority = 500;

$VirtualServerRule = {
rule_name => $rule_name,
priority => $priority
};
push @VirtualServerRuleList, $VirtualServerRule;
push @VirtualServerRuleAofA, [@VirtualServerRuleList];

# Pull down list of virtual servers
@vs_list = getVirtualServerList();

print "Adding iRule '$rule_name' to Virtual Servers\n";

# Iterate and do all virtuals individually.  We could bulk this into a single
# call but if the rule exists already on one of the virtuals, then the whole
# call will error out and rollback.
foreach $vs (@vs_list) {
print ">> $vs: ";
$soapResponse = $LocalLBVirtualServer->add_rule(
SOAP::Data->name(virtual_servers => [$vs]),
SOAP::Data->name(rules => [@VirtualServerRuleAofA])
);
$success = &checkResponse($soapResponse, 1);
print $success ? "SUCCEEDED\n" : "FAILED\n";
if ( $success ) { return; }

}
}

#============================================================================
sub rollbackMitigation()
#============================================================================
{
my ($file) = (@_);

  my $rule_name = &getiRuleName($file);

my $priority = 500;

$VirtualServerRule = {
rule_name => $rule_name,
priority => $priority
};
push @VirtualServerRuleList, $VirtualServerRule;
push @VirtualServerRuleAofA, [@VirtualServerRuleList];

# Pull down list of virtual servers
@vs_list = getVirtualServerList();

print "Removing iRule '$rule_name' from Virtual Servers\n";

foreach $vs (@vs_list) {
print ">> $vs: ";
$soapResponse = $LocalLBVirtualServer->remove_rule(
SOAP::Data->name(virtual_servers => [$vs]),
SOAP::Data->name(rules => [@VirtualServerRuleAofA])
);
$success = &checkResponse($soapResponse, 1);
print $success ? "SUCCEEDED\n" : "FAILED\n";
}

&removeiRule($file);
}
  
#============================================================================
sub checkResponse()
#============================================================================
{
my ($soapResponse, $ignore) = (@_);
my $success = 1;

if ( $soapResponse->fault )
{
  $success = 0;
print $soapResponse->faultcode, " ", $soapResponse->faultstring, "\n";
if ( ! $ignore ) {
exit();
}
}
return $success;
}

#============================================================================
# Main application logic
#============================================================================
if ( $sCmd eq "add" )
{
&deployMitigation($sRule);
}
else
{
  &rollbackMitigation($sRule);
}
Updated Jun 06, 2023
Version 2.0
No CommentsBe the first to comment