PingAM 7.5.0

Scripting environment

AM supports server-side scripts written in either JavaScript or Groovy.

Next-generation scripts and client-side authentication scripts must be written in JavaScript.

Scripting engine

AM implements a configurable scripting engine for each of the context types that are executed on the server.

The scripting engines contain configuration for security settings and thread pool management.

AM uses the following libraries:

  • Mozilla Rhino version 1.7.14 to run JavaScript.

    Rhino has limited support for ES6 / ES2015 (JavaScript version 1.7). For more information, refer to Rhino ES2015 Support.

  • Groovy version 3.0.10 to support scripting in Groovy.

Access Java classes

To access Java classes in a script, import classes in the following way:

  • JavaScript

  • Groovy

var fr = JavaImporter(
    org.forgerock.openam.auth.node.api.Action,
    javax.security.auth.callback.NameCallback
);
// Now use fr.Action, fr.NameCallback, and so on.
import org.forgerock.openam.auth.node.api.Action;
import javax.security.auth.callback.NameCallback;

Scripts can only import Java classes on the allowlist. AM defines an allowlist per script type.

Allowlists and denylists contain class names that are allowed or denied execution respectively.

Classes called by the script are checked against the allowlist first and must match at least one pattern in the list. The denylist is applied after the allowlist and classes matching any pattern are disallowed.

Legacy scripts

The legacy scripting engine lets you add classes to allowlists and denylists by specifying the class name or by using regular expressions.

You can also configure the scripting engine to make an additional call to the JVM security manager for each class that is accessed. The security manager throws an exception if a class isn’t allowed to execute.

Learn more about allowlisting and configuring script engine security in the following topics:

To reduce the need to allowlist Java classes, consider migrating your scripts to use the next-generation scripting engine, which includes enhanced built-in script bindings for accessing many common script operations and the ability to include third-party software with library scripts.

Next-generation scripts

To enhance security, the next-generation scripting engine for decision node scripts doesn’t support a configurable allowlist for Java classes.

Instead, check if next-generation bindings provide the functionality you need or implement the functionality as a reusable library script.

For information about next-generation bindings and library scripts, refer to:

In cases where reimplementation isn’t possible, you can request the functionality be included as a secure script binding in a future release.

Security considerations

Consider the following points when configuring the security settings within each script engine:

Use script bindings where possible

The predefined script bindings provide a stable API without the need to allowlist Java classes. Different bindings are available to different script types, or contexts.

For more information, refer to Script bindings.

The scripting engine only validates directly accessible classes

The security settings only apply to classes that the script directly accesses. If the script calls Foo.a() and that method calls Bar.b(), the scripting engine will be unable to prevent it. You must consider the whole chain of accessible classes.

Access includes actions such as:

  • Importing or loading a class.

  • Accessing any instance of that class. For example, passed as a parameter to the script.

  • Calling a static method on that class.

  • Calling a method on an instance of that class.

  • Accessing a method or field that returns an instance of that class.

Potentially dangerous Java classes are denylisted by default

All Java reflection classes (java.lang.Class, java.lang.reflect.*) are denylisted by default to avoid bypassing the security settings.

The java.security.AccessController class is also denylisted by default to prevent access to the doPrivileged() methods.

Don’t remove potentially dangerous Java classes from the denylist.
The allowlists and denylists match class or package names only

The allowlist and denylist patterns apply only to the exact class or package names involved. The script engine does not know anything about inheritance, so it is best to allowlist known, specific classes.

Thread pools

Each script is executed in an individual thread. Each scripting engine starts with an initial number of threads available for executing scripts. If no threads are available for execution, AM creates a new thread to execute the script, until the configured maximum number of threads is reached.

If the maximum number of threads is reached, pending script executions are queued in a number of buffer threads, until a thread becomes available for execution. If a created thread has completed script execution and has been idle for a configured time period, AM terminates the thread, shrinking the pool.

For more information on configuring script engine thread pools, refer to the Scripting service.