Forum Discussion
using perl iControl for system backups / archives
At my organization, we are trying to automate system backups of F5 LTM appliances. After considering many methods, I decided to use the iControl method mentioned.
http://devcentral.f5.com/wiki/default.aspx/iControl/PerlConfigSync.html
My only problem is I am trying to make the authentication fail and catch the authentication error. With the current code, when authentication fails the code simply aborts. Not being so knowledgeable about SOAP calls, I tried different things with no luck.
The reason I am after this is I am going to modify the script to handle more than one appliance and obviously we have non-standard logins (local auth) in our environment.
Any help would be greatly appreciated.
REgards,
Luke Yildirim
13 Replies
- Hamish
Cirrocumulus
Well.
The HTTP response that comes back will (Should, I tested this with my code and an incorrect password) be a 401 (Athentication required). I suspect if you're over-riding the authentication callbacks with browser basic auth, you'll probably get a second callback... Hold on... Maybe I can test that...
Yeah... OK, there will be more robsut methods of doing this, but we can take advantage of the fact that we can use the proxy() parameter to the SOAP initialisation to perform our default authentication, and if that fails, use the browser-basic response to try something else. You do this by having a function
----------------------------------------------------------------------------
Transport Information
----------------------------------------------------------------------------
sub SOAP::Transport::HTTP::Client::get_basic_credentials
{
print "SOAP::Transport::HTTP::Client::get_basic_credentials($icUser, $icPass)\n";
return "$icUser" => "$icPass";
}
in your code that over-rides the normal SOAP::Lite response to a 401 (Which is to give you an error). The initialisation call looks like this
my $userManagement = SOAP::Lite
-> uri('urn:iControl:System/ConfigSync')
-> proxy("$sProtocol://$icUser:$icPass\@$icServer:$icPort/iControl/iControlPortal.cgi");
Your auth callback will get called if the initial authentication fails. - Actually, the referenced sample includes some code I wrote to auto-insert the authentication headers in the first request.
$ConfigSync = SOAP::Lite -> uri('urn:iControl:System/ConfigSync') -> readable(1) -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi"); eval { $ConfigSync->transport->http_request->header ( 'Authorization' => 'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '') ); };
The use of passing user:pass in the URL is not standard and not guaranteed to work across all client toolkits. It looks from your post that your version of perl does allow it but my solution will work as well.
If you want to trap the exception in the code you can use the "eval" command like this:eval { $soap_response = $ConfigSync->get_configuration_list(); }; if ( $@ ) { print "ERROR: $@\n"; }
$@ will contain "401 F5 Authorization Required at ..." for invalid credentials.
-Joe - Haluk_Yildirim_
Nimbostratus
Hello:
Unfortunately the eval trick doesn't work in this occasion. Since I am calling the saveConfiguration subroutine, I modified it as follows:
sub saveConfiguration()
{
my ($configName, $saveMode, $quiet) = (@_);
my $success = 0;
if ( ("" eq $configName) or ("" eq $saveMode) )
{
&usage("save");
}
I Changed this to be an eval statement
eval { $soap_response = $ConfigSync->save_configuration
(
SOAP::Data->name(filename => $configName),
SOAP::Data->name(save_flag => $saveMode)
); };
This is the part I added
if ( $@ )
{
print "ERROR: $@\n"; exit;
}
if ( $soap_response->fault )
{
if ( 1 != $quiet )
{
print $soap_response->faultcode, " ", $soap_response->faultstring, "\n";
}
}
else
{
$success = 1;
if ( 1 != $quiet )
{
print "Configuration '$configName' saved successfully!\n";
}
}
return $success;
}
ERROR: 401 F5 Authorization Required at f5DeviceBackup.pl line 662.
Line 662 corresponds to
eval { $soap_response = $ConfigSync->save_configuration
In this setup, I had the auth check error disabled.
----------------------------------------------------------------------------
Transport Information
----------------------------------------------------------------------------
sub SOAP::Transport::HTTP::Client::get_basic_credentials
{
print "SOAP::Transport::HTTP::Client::get_basic_credentials($sUID, $sPWD)\n";
return "$sUID" => "$sPWD";
}
$ConfigSync = SOAP::Lite
-> uri('urn:iControl:System/ConfigSync')
-> readable(1)
-> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi");
eval { $ConfigSync->transport->http_request->header
(
'Authorization' =>
'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')
); };
if ($@)
{
print "Authentication to $sHost failed\n";
exit;
}
This is the part commented out
if ($ConfigSync->fault)
{
print "Authentication failed\n";
}
If I changed it back to how it was originally.
----------------------------------------------------------------------------
Transport Information
----------------------------------------------------------------------------
sub SOAP::Transport::HTTP::Client::get_basic_credentials
{
print "SOAP::Transport::HTTP::Client::get_basic_credentials($sUID, $sPWD)\n";
return "$sUID" => "$sPWD";
}
$ConfigSync = SOAP::Lite
-> uri('urn:iControl:System/ConfigSync')
-> readable(1)
-> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi");
eval { $ConfigSync->transport->http_request->header
(
'Authorization' =>
'Basic ' . MIME::Base64::encode("$sUID:$sPWD", '')
); };
if ($@)
{
print "Authentication to $sHost failed\n";
exit;
}
if ($ConfigSync->fault)
{
print "Authentication failed\n";
}
&checkParameters();
exit;
Code still exits prematurely.
401 F5 Authorization Required at f5DeviceBackup.pl line 174
where line 174 is "if ($ConfigSync->fault)"
sounds like evaluating any calls with the ConfigSync object simply fails.
I am going to read more on the SOAP::Lite module.
Regards,
Luke Yildirim - Anesh
Cirrostratus
Any update on this ?
- Anesh
Cirrostratus
Just tried the suggestion by Joe Pruitt and it works!!!
- Alexander_Hartm
Nimbostratus
Take a look at the BigIP::iControl module on CPAN. It does what F5 failed to do by putting all api calls into a module instead of a bunch of scripts.
- Alexander, we looked at putting the entire API library in a module but the complexities between all the parameter types for all 7000+ methods made it so we couldn't easily do it across the entire API hierarchy. The BIGIP::iControl module is a great use case for taking the APIs and pulling out a subset to make a useful library. If/When this gets to 100% coverage of the APIs, I'd be glad to take a look at getting the implementation built into our release distributions.
- Alexander_Hartm
Nimbostratus
Why was this no problem for e.g. the Python library? - The python library is dynamic in that it reads on the source WSDL and generates the proxy code on the fly. I consider myself a perl hack and honestly don't know the best way to package up all the APIs into a Perl module that makes sense with all the ways iControl uses parameters and return structures. I'd be game into looking at this is I can get guidance from a perl guru out there on how the package should be defined across all our interfaces and methods.
- wani_67522
Nimbostratus
Hello @nesh
I want to handle error HTTP401 when authenticatin failure occured. But I can't. Please show me how to work expectedly. I wrote below code,but still exits prematurely.So perl script ends with return code 0 regardless of authentication error.
use SOAP::Lite + trace => qw(method debug); use SOAP::Lite; use MIME::Base64; use Data::Dumper; my $sHost = $ARGV[0]; my $sUID = $ARGV[1]; my $sPWD = $ARGV[2]; my $sProtocol = "https"; my $sPort = 443; $SaveConfig = SOAP::Lite -> uri('urn:iControl:System/ConfigSync') -> proxy("$sProtocol://$sHost:$sPort/iControl/iControlPortal.cgi"); $SaveConfig->transport->http_request->header( 'Authorization' => 'Basic' . MIME::Base64::encode("$sUID:$sPWD",'') ); eval {$soap_response = $SaveConfig->get_configuration_list();}; if ($@) { print "ERROR: $@\n"; die "authentication error!!"; }Best regards.
You need a space after "Basic" in the authentication header.
$SaveConfig->transport->http_request->header( 'Authorization' => 'Basic ' . MIME::Base64::encode("$sUID:$sPWD",'') );The correct format of the header should be
Authorization: Basic FADSFZDSAFDSAFDSAFDASF
Without the space it's coming through as
Authorization: BasicFDSFDSDFASAFDSAF
Not sure if this answers the catching of the exception question, but it should allow you to authenticate with correct credentials.
-Joe
- wani_67522
Nimbostratus
thanks Joe.
I did a type mistake when writing in this web form. I actually run script with space like 'Basic ' and can't catch the exception of invalid authentication bye eval command.
I can get valid authentication with correct user and password.
I wonder whether there are problem on environment with running SOAP script.
environment with running SOAP Script is below
AIX 5.3.0 and Perl 5.8.8
regards.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
