Partial Evaluation
The TAM appliance has now been enhanced to include a compile endpoint that supports Partial Evaluation
What is Partial Evaluation?
Partial evaluation is a technique used in Open Policy Agent (OPA) to enhance policy evaluation efficiency. It involves precomputing parts of a policy decision that do not depend on specific input data, thereby minimizing the computational load during runtime when the actual input is provided
The key difference between partial evaluation and normal evaluation is in their outcomes. Normal evaluation results in a decision that can be immediately enforced (e.g., allow or deny). In contrast, partial evaluation produces new policies that can be evaluated later when the previously unknown inputs become available.
Instead of asking TAM to fully evaluate a policy, you can identify certain terms in your policy as unknown and use TAM’s compile API for partial evaluation. TAM will then return the remaining logic as an Abstract Syntax Tree (AST), which is easier to process programmatically and can be converted into other query languages, such as SQL or Elasticsearch DSL.
TAM Compile API requests contain the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
| input | any | Yes | The input document to use during partial evaluation (default: undefined). |
| unknowns | array[string] | No | The terms to treat as unknown during partial evaluation (default: [“input”]]). |
Partially Evaluate a Query
POST: /v1/compile/<<Package Namespace>>/<<Rule Name>>Content-Type: application/jsonAn example usecase
However, if the service needs to generate a report that lists all devices with outdated firmware, the policy engine would have to evaluate the firmware version of every device record in the database to filter out those with outdated versions. This process, which requires the policy engine to assess each record individually, would not be efficient for databases with a larger number of records
To address this issue, we would have the policy engine partially evaluate the policy using all known information (in our example, the method). The remaining logic, focused solely on the firmware version, would then be sent to the database for data filtering. By delegating the data filtering to the database, performance concerns would be effectively mitigated.
Sample Policy
package tam.example
default allow := false
allow { input.method == "GET" data.device.firmware_version <= input.firmware_version}The input passed to the policy looks like:
Example Request
POST: /v1/compile/tam.example/allowContent-Type: application/jsonRequest Body
{ "query": "data.{namespace}.{rule}{condition}", // This is an optional field if not provided it will take the default value of `data.{namespace}.{rule}==true` "input":{ "method":"GET", "firmware_version":12 }, "unknowns":["data.device"]}Result
{ "decision": { "id": "efff0ba0-ea43-4926-8889-7f9582faf60e", "result": { "queries": [ [ { "index": 0, "terms": [ { "type": "ref", "value": [ { "type": "var", "value": "lte" } ] }, { "type": "ref", "value": [ { "type": "var", "value": "data" }, { "type": "string", "value": "device" }, { "type": "string", "value": "firmware_version" } ] }, { "type": "number", "value": 12 } ] } ] ] } }}