Writing Lua scripts for the Scriptable Step
This page explains how to integrate Lua scripts in the Scriptable Step plugin. For more information on Lua itself see The Programming Language Lua.
The following configuration properties/fields are available in the Scriptable Step plugin:
Property | Mandatory | Description |
|---|---|---|
Inputs | optional | List of value map providers that provide input values for the Lua script. |
Script | mandatory | Source code of the Lua script. |
Outputs | optional | List of keys and data types to return values to Airlock IAM. Multiple scripting steps can segregate their return values by assigning their results to different namespaces. |
Input Secrets | optional | Secrets (that is, sensitive configuration values) can be provided to a script through environment variables. In the script context, secrets only exist in the IAM server. The script developer is responsible for avoiding leaking secrets. |
Namespace | optional | Namespace for output values to segregate output from multiple Lua scripts. |
Logging | The scripting language is extended with an |
Output
For a script to return output values to Airlock IAM, you must configure a list of keys and corresponding data types in the Outputs property and specify whether the key is required (mandatory).
The Outputs property exists of two parts:
- The key of a key-value output pair, set in the Key property.
- The expected data type(s) of a key-value pair, declared in the Script Output Declaration plugin. This plugin also defines whether the key-value pair is required (mandatory).
To integrate a script correctly, the following conditions must be met:
- The script must return all mandatory keys.
- The script cannot return undeclared keys.
- The data types of the output values must match the declaration.
- If the Outputs property is not configured, the
returnstatement is optional.
If one of these conditions is not met, an error will result, and the flow will be terminated as failed.
Output data types
IAM supports the following data types for script output values:
STRING: Any variable-length UTF-8 character sequence.BOOLEAN: Eithertrueorfalse. Binary digits are not allowed.NUMBER: An integer (64-bit constraints). Floating point values are currently not supported.DATE_TIME: An integer-type Unix timestamp in milliseconds.DATE: A valid date string in the formatyyyy-MM-dd(e.g., 2021-06-04).
Output elements
The script output values can be provided in various output elements. Output elements define the type and structure of the script output, such as lists, maps, or a single output value. You can combine these output elements at will. This allows for highly structured and nested output values, e.g., a list of roles for users.
When specifying the Script Output Declaration plugin, you in fact set the output element of the script.
IAM currently supports the following script output elements:
- List (List Output Element plugin):
Defines a list as script output. The size of the list is variable, and each element in the list must match the declared type. - Map (Map Output Element plugin):
Defines a key-value map element as script output. Two mutually exclusive modes are supported: - Key-value mode: The key-value pairs of the map are explicitly predefined, but each value may be a different type. Use this mode when keys are known and data types differ.
- Uniform mode: The map may contain a variable number of output values, but each entry must have the same type. This mode does not require keys. Use this mode when keys are dynamic and/or not known in advance, but data types are the same.
- Simple (Simple Output Element plugin)
Defines a simple script output type, such as numbers, strings, dates, or booleans.
Some output examples:
- Output 1: A list of roles, where each role is defined as a
STRINGoutput type: roles = {“roleA”, “roleB”, “roleC”}This output corresponds with the following settings in the Outputs property of the Scriptable Step plugin:
- Key:
roles - Script Output Declaration plugin:
- Output Type: List Output Element
- Type: Simple Output Element, with data type
STRING.
- Key:
- Output 2: A uniform map, where each value pair provides an NUMBER output value:
uniform_map_example = {valueA = 1, valueB = 2, valueC = 3}This output corresponds with the following settings in the Outputs property of the Scriptable Step plugin:
- Key:
uniform_map_example - Script Output Declaration plugin:
- Output Type: Map Output Element
- Uniform Declaration: Simple Output Element, with data type
NUMBER.
- Key:
- Output 3: A key-value map, with predefined key-value pairs whose output values are of different types, for example, an NUMBER value and a list of roles (see below):
explicit_map_example = {firstEntry = 1, secondEntry = {“roleA”, “roleB”, “roleC”}This output corresponds with the following settings in the Outputs property of the Scriptable Step plugin:
- Key:
explicit_map_example - Script Output Declaration plugin:
- Output Type: Map Output Element
- Key Value Declaration:
Row 1
- Key:
firstEntry - Script Output Declaration plugin: Simple Output Element as Output Type, and
NUMBERas data type.
- Key:
Row 2
- Key:
secondEntry - Script Output Declaration plugin: List Output Element as Output Type, then Simple Output Element es Type and
STRINGas data type.
- Key:
- Key:
For the examples following below, configure the Outputs property as follows:
- Key:
full_name - Script Output Declaration plugin:
- Output Type: Simple Output Element, with
- Type:
STRING
Script
To successfully run a script in the scriptable step plugin, at least the following function must be defined in the script property:
function iam_on_step_init ()
<your code>
return iam.output_map
endThe iam_on_step_init() function is called by IAM when starting the execution of a script.
Input
Input values are configured in the scriptable step plugin through value map providers. For this purpose, Airlock IAM provides a large number of plugins. Refer to the plugin documentation for further information on a particular value map provider.
All the examples in this text configure the Inputs property with a Context Data Map plugin. To read a context data item, the iam.input_map[<key>] table must be used in the script code.
The following example shows how a user's givenname and surname are concatenated into a property full_name. This property is then logged and finally returned to IAM for further use.
function iam_on_step_init ()
iam.output_map = {}
iam.output_map["full_name"] = iam.input_map["givenname"] .. " " .. iam.input_map["surname"]
iam.log:info("User with full name: " .. iam.output_map["full_name"])
return iam.output_map
endIf multiple value map providers contain a key with the same name, the value from the last value map provider will overwrite previous values.
Optional input values
When configuring value provider maps with optional values, it is the script's responsibility to check whether a particular value is present. In case of a missing value, the iam.input_map[<key>] will return the value nil.
The following code example will check if the key givenname is present or not:
if (iam.input_map["givenname"] ~= nil) then <logic if given name is present> else <logic if given name is absent> end
List all values provided to the script
The following code snippet will iterate over the table of input values provided to the script and output them to the IAM logfile:
for k, v in pairs(iam.input_map) do
iam.log:info("key : " .. k .. ", value: " .. v)
end The following code snippet will achieve the same result, with less formatting:
iam.log:info("Complete input map of GET request step: " .. iam.cjson.encode(iam.input_map))Input Secrets
Use the Input Secrets property to provide sensitive values to a Lua script. Sensitive values are transferred to the Lua script as environment variables. In the script, these values can be accessed through the IAM API function local secret = iam.secrets:get(<secretId>).
Once made available within the Lua script, secrets are retrieved as plaintext. The script developer is responsible for ensuring that secrets are not leaked (e.g., not logged).
The secretId can only consist of alphanumeric and underscore characters.
Namespaces
Namespaces are optional. They are used to assign a name to the value map from the output of a script. This may be necessary if multiple scripts in the same flow can return an output value with the same key.
If no namespace is configured, the default namespace is used. If several steps return the same key into the default namespace, the value of the scripting step executed last will overwrite the previous value.
Lua API functions
The Lua scripting language provides several built-in functions and types.
The print() function has been modified for Airlock IAM. It now writes messages to the appropriate Airlock IAM logfile with severity DEBUG.
All other built-in functions and types remain as implemented and documented by Lua.
Care should be taken when using the os object or functions like load(), loadfile(), or dofile(). These functions may have security-relevant side effects as they are run with the IAM user's permissions and can access processes and file system objects.
IAM API functions
Airlock IAM provides additional and IAM-specific functions for scripting with Lua:
Function | Description |
|---|---|
| This table contains all the key-value pairs provided to the script by configuring the Input Value Providers. Use the Date-time values include the precise time of day and are represented as a Unix timestamp with millisecond precision. Date values exclude the time, and are specified as strings in the format Note: If no value is present, “nil” is returned. |
| Use these functions to write messages to the Airlock IAM Log4J log files. The severity of the log message is determined by the function used in the script. All log message output of a Lua script will be prefixed with The Logging uses the standard error output stream. If the script or a library used in the script directly writes to standard error, this will be interpreted as an error message with severity ERROR. Data written to standard output will be ignored. |
| This function retrieves a value from secret storage and returns it as plaintext to the script. The key and value of secrets are defined in the IAM configuration. If the value is not present, “nil” is returned. |
| This is an alias for the bundled It is used implicitly by other IAM API functions. See Lua CJSON 2.1.0 Manual for more details. |
Error handling
The Config Editor does not verify the correctness of the Lua script syntax or semantics during configuration activation.
The following behavior is to be expected:
Syntax error | Syntax errors will be reported before the scriptable step is executed. The step will fail, and an error will be reported in the IAM log. |
Runtime error | Runtime errors will be reported if the error occurs during the execution of the scriptable step. The step will fail, and an error will be reported the IAM log. |
We recommended testing custom scripts before they are deployed with Airlock IAM.
The scriptable step supports the following error codes:
Error code | Description |
|---|---|
20 | A syntax error is present in the script source. |
21 | A runtime error occurred. This type of error is printed together with a Lua stack trace, showing the cause and location of the error. |
22 | The value returned by the
|
24 | The value returned by the This error occurs when data (e.g., a function reference) inside the expected output cannot be converted to a string. |
27 | An error occurred when using the IAM API functions (e.g. trying to access a secret using an identifier that isn't a string). |
126 | This error occurs if the operating system cannot execute the |
- | If a script does not terminate within 30 seconds, the script is aborted, and the following message is written with severity ERROR to the logfile:
|
Further information and links
External links:
- See The Programming Language Lua for more information about programming in Lua.
- See The Luarocks package manager for more information about using libraries with Lua.