Introducing OpalScript: Fully Customizable Access Logic Without the Ops Overhead
Introducing OpalScript: Fully Customizable Access Logic Without the Ops Overhead
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.
OpalScript delivers programmable automation for technical security teams hoping to achieve ultimate flexibility in access control.
Every organization has access patterns that don't fit neatly into checkbox configurations. Maybe your finance team needs a different approval flow during quarter-close. Maybe access to certain resources should only be granted to users who already have a prerequisite certification. Maybe your naming conventions encode environment information that should influence approval decisions.
Opinionated products handle the common cases well, but real organizations accumulate edge cases. These aren't bugs—they're the result of years of organic growth, acquisitions, compliance requirements, and business logic that made sense at the time. When your access management tool can't express these patterns, you're left choosing between manual workarounds or forcing your organization to change how it operates.
OpalScript is our answer to this problem: a scripting layer that lets you encode your organization's specific logic directly into Opal.
The Problem with Webhook-Based Automation
Many teams have attempted to automate access decisions using webhooks. When a request comes in, fire off a webhook to an external service, run some logic, and return a decision. Simple enough in theory.
In practice, webhook-based automation introduces friction:
Infrastructure overhead: You need to deploy, maintain, and monitor an external service just to run a few conditionals
Latency and reliability: Every decision now depends on network calls and external service availability
Limited context: Your webhook endpoint doesn't have direct access to Opal's access graph—who already has access to what, group memberships, existing permissions
Development friction: Making changes means updating, testing, and deploying a separate service
For simple automations, this overhead often isn't worth it. Teams end up either not automating at all, or building complex infrastructure for what should be straightforward logic.
OpalScript: Scripts That Run Inside Opal
OpalScript is a scripting language built on Starlark—the same Python-like language Google developed for Bazel. It lets you write automation logic that runs directly within Opal's infrastructure, with native access to your access graph data.
Here's what a simple auto-approval script looks like:
request = context.get_request() # Auto-approve short-duration requests with a ticket number if request.requested_duration_minutes and request.requested_duration_minutes <= 240: ticket = request.custom_fields.get("ticket_number", "") if ticket: actions.approve("Auto-approved: " + ticket) else: actions.comment("Short request, but missing ticket number") else: actions.comment("Requires manual review: duration exceeds 4 hours")
No external services. No network calls. No infrastructure to maintain.
Access-Aware Automation
The real power of OpalScript comes from its integration with Opal's access graph. Your scripts can query existing permissions to make smarter decisions.
Consider a common pattern: approving access only if someone already has prerequisite access. With webhooks, you'd need to call back into Opal's API, handle authentication, parse responses. With OpalScript:
request = context.get_request() SECURITY_TRAINED_GROUP = "550e8400-e29b-41d4-a716-446655440000" if request.target_user_id: is_trained = accesslib.check_access( request.target_user_id, SECURITY_TRAINED_GROUP ) if is_trained: actions.approve("User has completed security training") else: actions.deny("Security training required before access can be granted")
Your automation logic can reference your actual access graph—not a stale copy, not data you had to fetch and cache, but live permission data.
Safe by Design
Automation that makes access decisions needs to be trustworthy. OpalScript is designed with safety as a core principle:
Deterministic execution: Same inputs always produce the same outputs. No hidden state, no race conditions, no "it worked yesterday but not today" surprises.
Sandboxed runtime: Scripts can't make network calls, access the filesystem, or execute arbitrary code. They can only use the functions we explicitly provide.
Resource limits: Scripts timeout after 30 seconds and are limited to 1 million execution steps. A bug in your script can't take down your access management system.
Python-like syntax: If your team knows Python, they can write OpalScript. No new language to learn.
Real-World Patterns
Here are patterns we've seen teams implement:
Tiered Auto-Approval
Automatically approve low-risk requests (non-production, short duration, viewer access) while routing high-risk requests to manual review.
request = context.get_request() is_low_risk = True for resource in request.requested_resources: if "prod" in (resource.resource_name or "").lower(): is_low_risk = False if resource.access_level_remote_id == "admin": is_low_risk = False if is_low_risk: actions.approve("Auto-approved: low-risk access") else: actions.comment("Elevated access requires manual review")
Custom Field Validation
Enforce that certain fields are populated before approval.
request = context.get_request() justification = request.custom_fields.get("business_justification", "") if len(justification) < 20: actions.deny("Please provide a detailed business justification (at least 20 characters)") else: actions.approve()
Time-Based Policies
Different rules for different durations.
request = context.get_request() duration = request.requested_duration_minutes if duration is None: actions.comment("Permanent access requires VP approval") elif duration <= 60: actions.approve("Auto-approved: 1 hour or less") elif duration <= 480: actions.comment("Same-day access: pending manager review") else: actions.comment("Extended access: pending security review")
What's Next: Expanding OpalScript
Request review automation is the first application of OpalScript, but the architecture is designed to support scripting across Opal's platform. Here's where we're headed:
User Access Reviews
Today, OpalScript powers automated reviewers for access requests—deciding whether to approve, deny, or escalate incoming requests. But the same logic applies equally well to periodic access reviews (certifications). When you're reviewing whether existing access is still appropriate, you're asking fundamentally similar questions: Does this user still need this access? Does their current role justify it? Has the access been used recently?
With OpalScript in access reviews, you'll be able to automatically certify low-risk access that meets clear criteria, flag access that looks anomalous for human review, and apply the same organizational policies consistently across both new requests and existing entitlements. The scripts you write for request automation can inform your review automation, creating a unified policy layer across the access lifecycle.
Attribute and Tag Transformation
When you sync users and resources from external directories, the data rarely arrives in the exact format you need. Department names don't match your internal taxonomy. Manager relationships need to be derived from email patterns. Cost centers need to be mapped to business units.
Today, this means either accepting imperfect data or building ETL pipelines outside of Opal. With OpalScript, you'll be able to write transformation logic that runs during sync—normalizing fields, deriving attributes from naming conventions, and mapping external taxonomies to your internal structure.
Custom Provisioning Logic
Opal already integrates with the systems you use, but standard provisioning doesn't always account for organizational complexity. Maybe users in different sub-orgs need to be provisioned with different email addresses. Maybe certain departments require additional attributes set during provisioning. Maybe access to shared resources needs to be routed through different accounts depending on the user's cost center.
OpalScript will let you inject custom logic into the provisioning flow for systems Opal already supports. Rather than accepting one-size-fits-all provisioning behavior, you'll be able to encode your organization's specific rules—selecting the right identity, setting conditional attributes, or applying department-specific configurations—while Opal handles the underlying API calls, error handling, and audit logging.
The Long-Term Vision
The goal is to make OpalScript a general-purpose extension point across Opal. Anywhere you encounter a situation where you think "I wish I could just write a bit of code to handle this," OpalScript should eventually be the answer. Custom connector logic, complex approval routing, data enrichment during import, conditional notifications—all expressible in the same familiar scripting language with access to the same underlying platform capabilities.
Getting Started
OpalScript is available today for service user automations. When you create an automation triggered by access request events, you can choose to run a script instead of calling a webhook.
Scripts are version-controlled within Opal, so you can update your automation logic without coordinating external deployments. Execution history is tracked, making it easy to audit what decisions were made and why.
Want to try OpalScript? Check out our documentation or reach out to your account team to learn more.



