Post

4 followers Follow
0
Avatar

Question: How to include a secret value in a Remote Script task body while keeping the value invisible?

We use the RemoteScript tasks (Unix and Windows) to execute scripts on a remote server. Some of these scripts must be able to access remote services which require authentication.

Is it possible to pass credentials (username/password) from a RemoteScript task to the actual script invoked on the remote server?

Robin Tessier

Official comment

Avatar

On XL Release 5.x+, you will find that Unix.py is no longer part of the xl-remotescript-plugin JAR file.  

Instead, extract RemoteScriptWrapper.py from the plugin, insert the token replacement logic, and place the modified script under ext/remoteScript.  

With the token replacement logic included, the script should be coded as follows:

import sys

from com.xebialabs.xlrelease.plugin.overthere import RemoteScript

TASK_PASSWORD_TOKEN = '<taskPassword>'
script = task.pythonScript.getProperty("script")
script = script.replace(TASK_PASSWORD_TOKEN, taskPassword)
task.pythonScript.setProperty("script",script)

rs = RemoteScript(task.pythonScript)
exitCode = rs.execute()
output = rs.getStdout()
err = rs.getStderr()

if (exitCode == 0):
    print output
else:
    print "Exit code "
    print exitCode
    print
    print "#### Output:"
    print output
    print "#### Error stream:"
    print err
    print
    print "----"

sys.exit(exitCode)
Dave Roberts

Please sign in to leave a comment.

11 comments

0
Avatar

Hi Robin

Could you give an example of how you need to make the credentials available to the scripts? Is it via command-line arguments to those scripts, via environment variables, or in another way?

It's certainly possible to e.g. pass arguments to the scripts that are invoked - see http://snag.gy/7xrZv.jpg for an example. The challenge here is that XL Release does not know that ${password} is meant to be a "secret" variable, so it is treated like any other string variable: http://snag.gy/2nUX2.jpg.

I'm assuming that's not what is desired, but before going into possible approaches to deal with this, it would be good to understand in a bit more detail how we want to pass the credentials to the scripts in the first place ;-)

Regards

Andrew

Andrew Phillips 0 votes
0
Avatar

Hi Andrew,

Currently, the username and password are passed to the scripts via command-line arguments, but it could be any other way as long as the password remains hidden.

Robin Tessier 0 votes
0
Avatar

In fact, the username and password required by the scripts will always be the same as the Username and Password values entered in the RemoteScript task. It would be great if these values could be passed to the scripts, but it would be fine to add two variables to the task.

Robin Tessier 0 votes
0
Avatar

I haven't tried the following, but it might work:

getCurrentTask().pythonScript.password

Hes Siemelink 0 votes
0
Avatar

Hi Hes,

Since the RemoteScript task executes a script remotely (batch on Windows or shell on Unix/Linux), the script cannot include any references to XLRelease internal methods or variables. Any value must be passed explicitly to the script, causing a security hole by exposing the password.

Robin Tessier 0 votes
0
Avatar

Hi Robin

What Hes suggests will probably also work, but I think it may not even be necessary to use the XL Release API here since, as you point out, the password we need is already available to the task. The question is simply how to get the value into the script property without exposing it.

The simplest approach that comes to mind for me would be the following:

  1. Choose a token that we will replace with the password, and which will never be an "actual" part of the script property, e.g. <task-password>. I'm choosing a syntax here that intentionally does not look like a "normal" XL Release variable, just to avoid confusion.
  2. Change the implementation of the Remote Script task to replace all occurrences of <task-password> in the script body with the actual value of the task password.

To configure that, the steps would be roughly:

  1. Follow the instructions in the "Extracting the task implementation" section of the article "How To: Configure the standard Remote Script tasks to support additional Overthere options" to get the Unix.py task implementation script into SERVER_HOME/ext
  2. Modify the section of Unix.py that creates the SshRemoteScript as follows:
...
from com.xebialabs.xlrelease.plugin.overthere import SshRemoteScript

TASK_PASSWORD_TOKEN = '<task-password>'

script = script.replace(TASK_PASSWORD_TOKEN, password)
#print 'DEBUG: script', script
script = SshRemoteScript(username, password, sudo, address, remotePath, script)
exitCode = script.execute()
...

Here are some screenshots of the task configuration (http://snag.gy/85EdS.jpg) and the result when the "debug" line in the modified implementation is uncommented (http://snag.gy/R7FGO.jpg).

I've put the modified Unix.py file that I tested this with into a Gist in the XebiaLabs community Gist repository.

Hope that helps!

Andrew

Important: The code linked to is sample code only that is not officially supported by XebiaLabs. If you have questions, please contact our support team.

Andrew Phillips 0 votes
0
Avatar

Hi Andrew,

Thanks a lot, that looks exactly like what I need.

By the way, is there documentation on the WinrmRemoteScript class, or the more generic RemoteScript class, found in com/xebialabs/xlrelease/plugin/overthere? Some of their methods are exposed in Unix.py and Windows.py, but I could not find any reference to the 'replace' method included in your solution.

Thanks again,
Robin

Robin Tessier 0 votes
0
Avatar

Hi Robin

but I could not find any reference to the 'replace' method included in your solution

That's just regular Python, actually ;-) Well, Jython, to be precise.

Implementation tasks such as this one are written in Jython, and input properties on the tasks are simply variables that are available in the implementation. So at the point we are calling it, script is a string variable, which allows us to call Jython's replace method on it. We're not actually interacting with any XL Release-specific code there.

The implementation is indeed a little confusing in that we then assign instance of SshRemoteScript to the script variable...and that is an XL Release-specific class. But when we're calling replace on it, it's simply a string.

Hope that makes some kind of sense! See XL Release's custom task documentation for more details, and of course please let us know if you have any further questions.

Regards

Andrew

Andrew Phillips 0 votes
0
Avatar

Ok, I see where I got confused.

Your suggestion works, I simply modified the following line:

output = script.getStdout()

to

output = script.getStdout().replace(password, '********')

to obfuscate the password in the output.

Thanks again,
Robin

Robin Tessier 0 votes
0
Avatar

output = script.getStdout().replace(password, '********')

Ah, yes, good catch! I've updated the Gist with your suggestion.

Thanks!

Andrew

Andrew Phillips 0 votes