KBEC-00197 - Authentication using saved sessions and the Perl API

Article ID:360033192771
3 minute readKnowledge base

Description

The Perl API can be used outside of a CloudBees CD (CloudBees Flow) step to perform CloudBees CD (CloudBees Flow) actions. This is only possible after establishing a CloudBees CD (CloudBees Flow) session.

For security reasons, it is not possible to authenticate a CloudBees CD (CloudBees Flow) session without supplying a password.

When you look for alternatives in CloudBees CD (CloudBees Flow) to authenticate through the Perl script, getFullCredential works, however, that is accessible through a step only.

Using a distinct username works, however, there are no alternatives to specifying a password in the script using code similar to $ec->login('build', 'build');

Solutions

Reuse the CloudBees CD (CloudBees Flow) session after it is established.

Below and attached is an alternate method in Perl for logging in to and calling CloudBees CD (CloudBees Flow). While this does not eliminate the need to log in, it does minimize it. The key is the "saveSessionFile" call. There is one case where you will not get the same behavior, when there is an ambient session in the environment (COMMANDER_SESSIONID). In the ambient session case, the API assumes you are running inside a step and sessions are being managed externally. In that case, saveSessionFile() will return immediately without writing the session.

In this Perl script, all API calls are made through "invokeCommander". When invokeCommander finds an expired session or no credentials at all, it will ask the user to log in. This example code retains some global variable references as it is extracted from ecclientpreflight.pl, which is found in the src directory of the CloudBees CD (CloudBees Flow) distribution.

#------------------------------------------------------------------------------


# loginToCommander


#


#       Establishes a connection to the Flow server and logs in via the


#       API, saving the server object for future API calls.


#


# Arguments:


#       username -          The name of the Flow user to login as.


#       password -          The password of the user.


#------------------------------------------------------------------------------





sub loginToCommander()


{


    if (!defined($::gPassword) || $::gPassword eq "") {


        # Retrieve the Flow user's password.





        $::gPassword = getPassword("Enter the password for Flow user $::gUserName: ");


    }





    display("Logging into ElectricFlow");


    debug("Logging in as \"$::gUserName\"");





    if (defined($ENV{ECPREFLIGHT_TEST})) {


        return;


    }





    invokeCommander("login", [$::gUserName, $::gPassword]);


    $::gCommander->saveSessionFile();


}





#------------------------------------------------------------------------------


# invokeCommander


#


#       Run a command on the Flow server and return the results,


#       optionally suppressing certain errors.


#


# Results:


#       A pair of values is returned, the first of which indicates whether an


#       error that was chosen to be suppressed was found.  If the error was


#       found, then the second value contains the error message.  Otherwise,


#       the second value is an XPath element containing the server's response


#       to the method invocation.


#


# Side Effects:


#       If an error occurs and it was not chosen to be suppressed, we generate


#       an error message on standard error and exit the application.


#


# Arguments:


#       functionName -      The name of the Flow method to invoke.


#       functionArgs -      The arguments to the method being invoked.  This


#                           should be an array ref.


#       suppressError -     A string containing an error code or message from


#                           the server response that should be ignored.


#------------------------------------------------------------------------------





sub invokeCommander($$;$)


{


    my ($functionName, $functionArgsRef, $suppressError) = @_;


    debug("Invoking function $functionName");


    my @functionArgs = @{$functionArgsRef};


    my $xpath = $::gCommander->$functionName(@functionArgs);


    my $errMsg = $::gCommander->getError();


    if (defined($errMsg) && $errMsg =~ m{ExpiredSession|NoCredentials}) {


        loginToCommander();


        $xpath = $::gCommander->$functionName(@functionArgs);


        $errMsg = $::gCommander->getError();


    }


    if (defined($errMsg) && $errMsg ne "") {


        if (defined($suppressError) && $suppressError ne "" &&


                index($errMsg, $suppressError) >= 0) {


            return (1, $errMsg);


        } else {


            error($errMsg);


        }


    } else {


        $xpath = $xpath->findnodes('/responses/response')->get_node(0);


        return (0, $xpath);


    }


}