-
Notifications
You must be signed in to change notification settings - Fork 176
[Draft] OPA Plugin: Mapping Cedar via Rego
Open Policy Agent allows us to extend the behavior of the OPA runtime via plugins. This lets us define custom behavior such as logging or executing extra Go code. Using the cedarling_go binding, we are thus able to run an instance of Cedarling inside the OPA binary.
Currently, the cedarling_opa plugin simply boots the Cedarling with a configurable bootstrap file and does not provide any additional functionality. This wiki page is for the purposes of documenting the mapping from Rego to Cedarling concepts in order to implement rego verbs and functions.
sequenceDiagram
participant Client
participant OPA
participant Rego
participant Builtin as cedarling_opa.authorize
participant Plugin as Cedarling Binding (Go)
participant Cedarling
participant Cedar
Client->>OPA: Query (input)
OPA->>Rego: Evaluate rego policy
Rego->>Builtin: cedarling_opa.authorize(input)
Builtin->>Plugin: Invoke Go built-in
Plugin->>Cedarling: Build + send request
Cedarling->>Cedar: Evaluate cedar policies
Cedar-->>Cedarling: Decision + diagnostics
Cedarling-->>Plugin: Result
Plugin-->>Builtin: Normalized JSON
Builtin-->>Rego: result
Rego-->>OPA: decision object
OPA-->>Client: Response
In this flow, Rego acts as a thin wrapper between the OPA runtime and the cedarling_go binding. The intended way to use this would be to avoid complex Rego policies; instead, Rego simply calls the new verbs authorize and authorize_unsigned, while the Cedar policies are considered to be the source of truth.
| Cedar Concept | Cedarling API | Rego/OPA Equivalent |
|---|---|---|
| Principal | EntityData | input.principal |
| Action | String | input.action |
| Resource | EntityData | input.resource |
| Context | Dictionary | input.context |
| Decision | Allow/Deny |
allow boolean |
| Diagnostics | reason() | trace? logging? |
Input spec:
{
"principal": {
"cedar_entity_mapping": {
"entity_type": "User",
"id": "some_id"
}
}
"action": "read",
"resource": {
"cedar_entity_mapping": {
"entity_type": "Document",
"id": "some_document"
}
},
"context": {}
}Output spec:
{
"decision": true,
"reasons": ["policy-1"],
"errors": [],
"request_id": "uuid"
}Rego example:
package cedarling_opa
default allow := false
result := cedarling_opa.authorize_unsigned(input) # new rego verb: authorize_unsigned
allow {
result.decision
}
deny_reasons := result.reasonsInput spec:
{
"tokens": [
{
"mapping": "Jans::Access_token",
"payload": "eyJhbGciOiJIUzI1NiIs..."
}
],
"action": "read",
"resource": {
"type": "Document",
"id": "doc1",
"attrs": {}
},
"context": {}
}Output spec:
{
"decision": true,
"reasons": ["policy-1"],
"errors": [],
"request_id": "uuid"
}Rego Example:
package cedarling_opa
default allow := false
result := cedarling_opa.authorize(input) # new rego verb: authorize
allow {
result.decision
}
deny_reasons := result.reasons