Forum Discussion

Haluk_Yildirim_'s avatar
Haluk_Yildirim_
Icon for Nimbostratus rankNimbostratus
Dec 10, 2009

using perl iControl for system backups / archives

Hello:

 

 

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's avatar
    Hamish
    Icon for Cirrocumulus rankCirrocumulus
    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
  • 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's avatar
    Anesh
    Icon for Cirrostratus rankCirrostratus

    Just tried the suggestion by Joe Pruitt and it works!!!

     

    • Joe_Pruitt's avatar
      Joe_Pruitt
      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.
    • Joe_Pruitt's avatar
      Joe_Pruitt
      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.
  • 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's avatar
      wani_67522
      Icon for Nimbostratus rankNimbostratus

      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.