Each script type has its own
context and actions modules tailored to that
automation scenario.Overview
Request Review scripts run when an access request is assigned to a service user for review. The script can automatically approve, deny, or add comments to the request. This guide details the context and action modules you can use to get started, as well as the best practices and limitations when using OpalScript. For use case specific sample scripts, see our examples.Quick Start
The simplest script approves all requests:context Module
Thecontext module provides read-only access to the request being reviewed.
Get the request object
context.get_request() returns the Request object being reviewed.
None
Contains information about the access request
actions Module
Theactions module provides methods to take action on the request.
Approve a request
actions.approve([comment], [duration_minutes]) approves the request.
Optional comment to add to the approval.
Optional override for the access duration. Must be a positive integer. If different from the originally requested duration, a notice is automatically appended to the comment.
Deny a request
actions.deny(comment) denies a request. A comment is required to explain the denial.
Comment explaining the denial.
Comment on a request
actions.comment(comment, [duration_minutes]) adds a comment without changing the request status. Useful for flagging requests or adding context for manual reviewers.
Comment to add.
Optional override for the access duration. Must be a positive integer. If different from the originally requested duration, a notice is automatically appended to the comment.
Pause execution
actions.pause(minutes) pauses script execution and resumes from the same point after the specified time. Any actions already taken before the pause are skipped on replay.
Number of minutes to pause. Must be between 1 and 1440 (24 hours).
Poll a condition
actions.poll(function, minutes, max_iterations) repeatedly calls function at the given interval until it returns True or the maximum iterations are reached. Returns True if the function succeeded, False if it ran out of iterations.
A function that takes no arguments and returns a boolean. Execution resumes when it returns
True or max_iterations is exhausted.Interval between calls in minutes. Must be between 1 and 1440.
Maximum number of times to call the function. Must be between 1 and 50.
Objects
Request object
Returned bycontext.get_request() and contains information about the access request.
| Attribute | Type | Description |
|---|---|---|
id | String (UUID) | Unique identifier for the request |
reason | String | The reason provided by the requester |
requester_id | String (UUID) | ID of the user who created the request |
target_user_id | String or None | ID of the user being granted access (if applicable) |
target_group_id | String or None | ID of the group being granted access (if applicable) |
requested_duration_minutes | int or None | Requested access duration in minutes |
status | String | Current status (e.g., "PENDING", "APPROVED", "DENIED") |
requested_resources | List[RequestedResource] | Resources included in this request |
requested_groups | List[RequestedGroup] | Groups included in this request |
custom_fields | Dict[String, value] | Custom field values from the request template |
RequestedResource object
Represents a resource included in the request. Returned in the Request object.| Attribute | Type | Description |
|---|---|---|
id | String (UUID) | Unique identifier for this requested resource entry |
resource_id | String (UUID) | ID of the resource being requested |
resource_name | String or None | Name of the resource |
resource_type | String or None | Type of the resource (e.g., "AWS_IAM_ROLE") |
access_level_name | String | Display name of the requested access level |
access_level_remote_id | String | Remote identifier for the access level |
RequestedGroup object
Represents a group included in the request. Returned in the Request object.| Attribute | Type | Description |
|---|---|---|
id | String (UUID) | Unique identifier for this requested group entry |
group_id | String (UUID) | ID of the group being requested |
group_name | String or None | Name of the group |
group_type | String or None | Type of the group (e.g., "OKTA_GROUP") |
access_level_name | String | Display name of the requested access level |
access_level_remote_id | String | Remote identifier for the access level |
Custom Fields
Thecustom_fields attribute is a dictionary containing values from the request template’s custom fields. The keys are field names, and values depend on the field type:
| Field Type | Value Type | Example |
|---|---|---|
| Short Text | String | "JIRA-1234" |
| Long Text | String | "Detailed justification..." |
| Boolean | bool | True |
| Multi-Choice | String | "Option A" |
Constraints & Limits
OpalScript enforces limits to ensure safe, predictable execution:| Constraint | Limit | Description |
|---|---|---|
| Script Size | 100 KB | Maximum script length |
| Execution Time | 30 seconds | Scripts timeout after 30 seconds |
| Execution Steps | 1,000,000 | Maximum operations to prevent infinite loops |
Unsupported Operations
For security and reliability, OpalScript does not support:- External HTTP calls: Scripts cannot make network requests
- File I/O: Scripts cannot read or write files
- Direct database access: All data access goes through provided modules
- Import statements: All modules are pre-loaded
- While loops: Use
forloops withrange()instead
Error Handling
Scripts can fail due to various errors. Understanding common error types helps you write more robust scripts.Syntax Errors
None Value Errors
Type Errors
Best Practices
- Check for None before using optional attributes
- Use
.get()with defaults when accessing dictionary values - Keep scripts focused - do one thing well
- Test with edge cases - empty strings, None values, missing fields

