Writing Custom Scripts

The following describes how to write a custom system script used to create a resource profile. Once the system script is written, you may add or update a resource profile that contains the script and then add a system of that type.

Scripts must be written in JavaScript, extensive JavaScript knowledge is not required.

The script must implement two functions as follows:

Functions

getAttributes()

The script must implement the getAttributes() function. It indicates the functionality your script provides and additional configuration information.

Example:

Copy
function getAttributes() {
var attributes = {
CanChangeOwnPassword: false,
AdministrativeAccountSupported: false
};
return attributes;
}

The remaining functions you write consist of send and expect verbs that are invoked with the sshSend() and sshExpect() functions.

verifyPassword()

The verifyPassword() function is required and allows Privileged Access Service to determine if a username/password combination is valid. When the verifyPassword() function is invoked, Privileged Access Service logs into the system and nothing more may be needed to validate that the user name and password combination is valid.

Example:

The following is an implementation of verifyPassword() that ensures a command prompt outputs by the target system:

Copy
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}

sshExpect()

The following are true for sshExpect():

  • The sshExpect() function is called and commands to wait until the target system outputs the string "Prompt> ".
  • If the target system does not output the expected string, your script returns an error code.
  • The argument to the sshExpect() function is a list of regular expressions to expect.
  • If the result.MatchIndex returned is less than zero, the expected string was not output by the target system.

Putting It All Together

Finally, put together the complete script as follows:

Copy
function getAttributes() {
var attributes = {
CanChangeOwnPassword: false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}

You can now create a new resource profile with this script and start adding systems of this type. This script allows you to create systems and accounts with vaulted passwords, control who has access to those accounts, initiate workflow for requesting temporary access to a system, and audit use of an account.

Testing the Script

A standalone SSH test utility allows you to test and debug your script before using it to create a resource profile. The test utility runs on Windows systems and is a command-line tool suitable for integration into a test harness. To download the SSH test utility, from the Admin Portal, navigate to Download > Tools > Delinea SSH Test Kit.

Test Loading

Take the script you created and add it to a file entitled "device-script.js". You can now add a number of arguments to SSH test utility, many of which are optional. You must, however, specify the --script parameter, and one of the "operation" parameters such as --load.

Example:

Copy
> SshTest --script device-script.js --load
TEST(Info): Load script result = Success
>

The --load parameter asks SSH test utility to load the JavaScript, test for syntax errors, invoke the getAttributes() function and verify that the attributes are legal.

Example:

Modify the script to include a syntax error by removing the colon after CanChangeOwnPassword in the getAttributes() function as follows:

Copy
function getAttributes() {
var attributes = {
CanChangeOwnPassword false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {

// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}

// Password is OK.
return Success;
}

Now, SSH test utility reports the error:

Copy
> SshTest --script device-script.js --load
TEST(Error): no viable alternative at input 'CanChangeOwnPassword' at line 4:9
>

Similarly, put the colon back in and change the attribute to an invalid one:

Copy
function getAttributes() {
var attributes = {
ThisIsNotAValidAttribute: false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {

// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}

// Password is OK.
return Success;
}

SSH test utility reports the error as follows:

Copy
> SshTest --script device-script.js --load
TEST(Error): Attribute 'ThisIsNotAValidAttribute' is not valid
>

Testing Password Verification

To test your verifyPassword() function, use the --verify parameter and supply additional arguments.

Example:

Copy
> SshTest --script device-script.js --verify --host hatter-rh.richl.devp --user local2 --password local2pass
TEST(Info): Verify password result = Success
>

Using Script Parameter Shortcuts

Many SSH test utility parameters have shortcuts for the parameter names.

Example, instead of:

Copy
> SshTest --script device-script.js --verify --host hatter-rh.richl.devp --user local2 --password local2pass

use:

Copy
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass

Using Script Logging

You can get additional logging output to help diagnose issues with your scripts. For example, to see details of the "send/expect" interaction with the target system, use the --show-detailed-log parameter:

Example:

Copy
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log
INTE(Verbose): getAttributes() completed using 3 statements (start=4, end=7)
INTE(Verbose): sshExpect: expect=(Count=1, Values=('Prompt> $'))
INTE(Verbose): Matching: 'Prompt> $' to '^[]0;local2@hatter-rh:~^GPrompt> '
INTE(Verbose): Matched: 'Prompt> $' to 'Prompt> '
INTE(Verbose): sshExpect: found 'Prompt> $' with match index 0
INTE(Verbose): verifyPassword() completed using 4 statements (start=7, end=11)
TEST(Info): Verify password result = Success
>
  • Messages with an INTE prefix indicate messages generated internally by the script processor.
  • Messages with a TEST prefix come directly from the SSH test utility.

Additional Logging

You can add additional logging into your script to help diagnose problems. For example change your script as follows:

Copy
function getAttributes() {
var attributes = {
CanChangeOwnPassword false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
verbose("Starting execution of verifyPassword");
verbose("userName = " + verifyPasswordInfo.userName);
verbose("userPassword = " + verifyPasswordInfo.userPassword);

// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
verbose("Everything went OK");

// Password is OK.
return Success;
}

Messages that you generate from your script have a JINT prefix to indicate they came from the JavaScript interpreter:

Copy
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log
JINT(Verbose): Starting execution of verifyPassword
JINT(Verbose): userName = local2
JINT(Verbose): userPassword = <hidden>
JINT(Verbose): Everything went OK
TEST(Info): Verify password result = Success
>

View Password Parameter

For security, the password is scrubbed from the output of the SSH test utility. To view the password passed to your verifyPassword() method, use the --show-passwords option.

Copy
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log --show-passwords
JINT(Verbose): Starting execution of verifyPassword
JINT(Verbose): userName = local2
JINT(Verbose): userPassword = local2pass
JINT(Verbose): Everything went OK
TEST(Info): Verify password result = Success
>

If you are verifying a username and password and see that your verifyPassword() function is not called, there may be a connection issue.

In the following example, where the target system is not running, you might see:

Copy
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass
TEST(Error): Connection failed: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 172.27.14.237:22

Connection Details Parameter

In the unlikely event there is an error in establishing the connection, you can use the --show-connection-log parameter to see all the details of connection establishment.