39 posts categorized "perl"

03/03/2014

iControl Perl - Authentication

Another thing that each of these iControl Perl scripts is going to need to do is to authenticate with the BigIP ltm. Since you are connecting using https, you are going to be using Basic Authentication. Below are a couple of options for setting authentication up.

The first method, which seems to be the most popular, is to insert the userid and password into SOAP::Lite's get_basic_credentials method, which would get set prior to creating your soap request. For example:

my $host = "the_bigip_hostname_or_ipaddr"
my $port = "443";
my $uid = "some_user_id";
my $pwd = "some_password";

sub SOAP::Transport::HTTP::Client::get_basic_credentials {
    return "$uid" => "$pwd";
    }

# This is the base request
my $req = SOAP::Lite
    -> uri('urn:iControl:LocalLB/Pool')
    -> proxy("https://$host:$port/iControl/iControlPortal.cgi");

Using this method, the request will get sent to your bigip, the bigip will respond with a 401 Unauthorized status code, and then the request will be retried with the UserID and password. If you want to skip the initial authentication failure, add the following code after the code which creates the request. This will add an Authorization header with your encoded userid and password on every request:

# Add authorization header; Otherwise the
# initial request will fail
    eval { $req->transport->http_request->header (
        'Authorization' => 'Basic ' . MIME::Base64::encode("$uid:$pwd", '')); };

The second method employs a similar technique to what you would employ if you were setting an ftp_proxy environment variable in your .bashrc—insert the userid and password separated by a colon and then separate the password from the URL with an @ symbol. For example:

export ftp_proxy=$USERID:$PASSWORD@ftp.proxy.address

With iControl, you would modify the proxy parameter in your request to use the same syntax:

my $host = "the_bigip_hostname_or_ipaddr"
my $port = "443";
my $uid = "some_user_id";
my $pwd = "some_password";
my $req = SOAP::Lite
    -> uri('urn:iControl:LocalLB/Pool')
    -> proxy("https://$uid:$pwd@$host:$port/iControl/iControlPortal.cgi");

Other Posts in This Series

<< Previous iControl Perl - User Accounts

02/24/2014

iControl Perl - User Accounts

Figuring out what kind of user account your iControl script is going to require is about as simple as figuring out what rights a regular user is going to need. If your script is simply echoing back statistics or pools or pool member stats or virtual server configurations, you don't need a user account that is going to have Administrative rights to your BigIP. You can get away with "Auditor" rights for these types of scripts. They also will not require any special terminal rights since they are going to be executed remotely.

If your script is going to enable or disable nodes or pool members, "Operator" rights should be sufficient. The "Application Editor" role will give your script the ability to modify pools like setting weights, adding or deleting pool members, or modifying nodes and pools to attach monitors.

Operationally, it is tempting to just create an Administrative user that can do whatever it wants but I'd discourage that practice when you consider the security ramifications. You might, at some future point, want to distribute your scripts to junior members of your team but if you're embedding an Administrative account in your script, you may inadvertently be providing folks with the access that they shouldn't have so I encourage people to use an account that has the lowest privileges available to get the task done.


Other Posts in This Series

iControl Perl - Getting Started << Previous | Next >> iControl Perl - Authentication

02/21/2014

iControl Perl - Getting Started

After having the BigIP's in house for a while now and spending a bit of time writing iRules, I felt like it was time to give iControl a try. My intentions were noble: Kill two birds with one stone by learning iControl and Java. Something about it keeps drawing me back to Perl though. It is hard to explain but, for me, Perl is like a sketchpad. I can scribble away at a script until I have something that works. It might not be museum-worthy but it still looks good and conveys what I'm trying to do rather nicely. I like the sigils, too.

Back when I was a kid, I was a huge comics fan and I loved to draw. One of the best books I had ever bought at the time was How To Draw Comics The Marvel Way. In it, Stan Lee and John Buscema outlined some techniques that comic illustrators commonly use and the technique that I found that worked best for me was the scribbling/scuplting technique. Instead of drawing a human form based on circles and cylinders, you'd get a basic stick figure in place and then start scribbling lightly around it until you got the form you wanted. Once your superhero's form was correct, you'd then work out the hard parts like the face or hands.

For me, I like Perl when writing scripts because you can fairly quickly "sketch" out the main outline of your program and get all the forms together, then sweat over the face and hands once you've figured out the main form of the script. Ruby and Python could do this too but, as I alluded to earlier, Perl has the sigils that syntax highlighters easily catch and Perl's "There's more than one way to do it" let's me get something in place that then invites helpful critique from the community.

iControl is useful but the Perl examples can be frustrating for someone just getting started with iControl and SOAP. Does no one run Perl scripts with warnings turned on like everyone suggests they do? Getting started with Perl, SOAP::Lite, and iControl can be a bit frustrating if you're purely going by what's documented in the SDK or on DevCentral. If you are also just getting started, here are a couple of pointers that should go in every script before you start sketching further:

After starting off each script with the shebang (I use #!/usr/bin/env perl always instead of naming a specific perl location because I'd rather install perlbrew everywhere instead of relying upon the Unix admin installed system perl), add the following:

#!/usr/bin/env perl

use Modern::Perl;
use Mozilla::CA;
#use Data::Dumper;
#use SOAP::Lite +trace => [ qw (all -transport) ];
use SOAP::Lite;
use MIME::Base64;

use iControlTypeCast;

# It's always easier if you just use Mozilla::CA
# for your certificate store
$ENV{HTTPS_CA_FILE} = Mozilla::CA::SSL_ca_file();

# Add any variable declarations like:
my $uid = "my_bigip_userid";
my $pwd = "my_bigip_password"

# Set up request's transport info
sub SOAP::Transport::HTTP::Client::get_basic_credentials {
    return "$uid" => "$pwd";
    }

use Modern::Perl;, among other things, sets "strict" and "warnings" and automatically enables a bunch of modern Perl-ly things like letting you use features like say without havng to bother setting a bunch of use feature declarations in your script.

use Mozilla::CA; because it's the same set of CA certificates that Firefox uses. You don't need to worry about handling the self signed certificate the BigIP uses. Just set $ENV{HTTPS_CA_FILE} = Mozilla::CA::SSL_ca_file(); in your script and you're good to go.

use Data::Dumper; and use SOAP::Lite +trace => [qw (all -transport) ]; are for debugging purposes. The [qw (all -transport) ]; line will give you some helpful data that displays the SOAP request and response while stripping out some of the http portions of the request and response. Uncomment then when you want to use them.

use SOAP::Lite because you have to and use MIME::Base64 because you need to encode your Basic Auth userid and password if you want to avoid an initial reject coming from your BigIP due to the userid and password not being present in the request header.

use iControlTypeCast; is special. It is a custom perl module included with and referenced by almost every script in the SDK. The Perl docs don't state that you need it but you need it. Without it, you end up generating "Unrecognized type" errors if you execute a method that returns data referencing a type that resides outside of the type of request you are executing. For example, my requests for get_member_monitor_state()ended up generating Unrecognized Type warnings because the type returned was iControl::LocalLB/SessionStatus while the request was within iControl::LocalLB/Pool. use iControlTypeCast;needs to follow use SOAP::Lite; because SOAP::Lite is a dependency and if you use warnings; like we all are supposed to, iControlTypeCast.pm needs the following edits:

#Implement Typecast for iControl enumeration Elements
no warnings qw(redefine);
sub SOAP::Deserializer::typecast
{
	my ($self, $value, $name, $attrs, $children, $type) = @_;
	my $retval = undef;
        if (defined($type) && exists($urnMap->{$type}) && $urnMap->{$type} == 1)
	#if ( 1 == $urnMap->{$type} )
	{
		$retval = $value;
	}
	return $retval;
}
use warnings qw(redefine);
# End Of File

One additional note on use iControlTypeCast. Some scripts I've written that contain iControlTypeCast.pm in the same directory as the script ended up not being able to find it, especially when run from my Ubuntu box. If that happens, a quick workaround is to create a "modules" directory somewhere, copy iControlTypeCast.pm to it, and then use use lib '/path/to/your/modules'; instead of use iControlTypeCast;.

Replace the information between #Implement Typecast for iControl enumeration Elements and # End Of File with the data above, which will help with those scripts written to use warnings;.


Next Post in This Series

Next >> iControl Perl - User Accounts