AST Walker
OPA has a feature called partial evaluation which has several interesting applications. With partial evaluation, callers specify that certain inputs or pieces of data are unknown. OPA evaluates as much of the policy as possible without touching parts that depend on unknown values. The result of partial evaluation is a new policy that can be evaluated more efficiently than the original. The new policy is returned to the caller as an AST.
The returned AST thus represents a strategy, rather than a result. It may be cached and reused. It may also be converted to other forms, e.g. a SQL query condition, or elastic search query.
The ASTWalker module provides a framework to traverse the AST returned from a partial evaluattion. It specifies a Visitor interface that callers can implement to perform custom operations on the AST. The ASTWalker module also provides a default implementation of the Visitor interface that can be used to perform common operations on the AST.
Included in the ASTWalker module are implementations of the Visitor interface that can be used to:
- Create a easy to use Julia representation of the AST. This is provided by the
ASTWalker.AST.ASTVisitortype. - Create a SQL query condition from the Julia representation of the AST. This is provided by the
ASTWalker.SQL.SQLVisitortype.
An example of how it can be used is shown below:
import OpenPolicyAgent: ASTWalker
import OpenPolicyAgent.ASTWalker: AST, SQL
import OpenPolicyAgent.ASTWalker.AST: ASTVisitor
import OpenPolicyAgent.ASTWalker.SQL: SQLVisitor, SQLCondition, UnconditionalInclude, UnconditionalExclude
# invoke the partial evaluation endpoint
partial_query_schema = OpenPolicyAgent.Client.PartialQuerySchema(; ...)
response, _http_resp = OpenPolicyAgent.Client.post_compile(
compile_client;
partial_query_schema = partial_query_schema,
)
# crete a Julia representation of the AST
ast = OpenPolicyAgent.ASTWalker.walk(ASTVisitor(), result)
# Provide a mapping of schema names and table names that can be used to convert policy paths to SQL table names
const SCHEMA_MAP = Dict{String, String}(
"data" => "public",
"public" => "public",
)
const TABLE_MAP = Dict{String, String}(
"reports" => "juliahub_reports",
)
# create a SQL query condition from the AST
sqlvisitor = SQLVisitor(SCHEMA_MAP, TABLE_MAP)
sqlcondition = OpenPolicyAgent.ASTWalker.walk(sqlvisitor, ast)
# sql condition should be a SQLCondition object
if isa(sqlcondition, UnconditionalExclude)
# all rows should be excluded
elseif isa(sqlcondition, UnconditionalInclude)
# all rows should be included
else
# `sqlcondition.sql` contains a string with the SQL query condition
endMore details of AST walker, and the included visitors can be found in the reference documentation.