Skip to content

OPA Policy Schema

jitsudo embeds OPA (Open Policy Agent) as a Go library. This page documents the exact input document structure and expected output for each policy type.

All policy types receive the same input document. The structure is stable across jitsudo versions.

{
"user": {
"email": "alice@example.com",
"groups": ["sre", "oncall"]
},
"request": {
"provider": "aws",
"role": "prod-infra-admin",
"resource_scope": "123456789012",
"duration_seconds": 7200,
"reason": "Investigating P1 ECS crash — INC-4421",
"break_glass": false,
"metadata": {}
}
}
FieldTypeSourceDescription
user.emailstringOIDC email claimThe requester’s email address. Used as the primary identity in audit logs and bindings.
user.groupsstring[]OIDC groups claimGroup memberships from the IdP token. Empty if the IdP does not include a groups claim.
FieldTypeSourceDescription
request.providerstringjitsudo request --providerCloud provider: aws, azure, gcp, kubernetes
request.rolestringjitsudo request --roleProvider-specific role name
request.resource_scopestringjitsudo request --scopeProvider-specific scope (AWS account ID, GCP project, K8s namespace)
request.duration_secondsnumberjitsudo request --durationRequested elevation duration, converted to seconds
request.reasonstringjitsudo request --reasonHuman-readable justification text
request.break_glassbooleanjitsudo request --break-glasstrue if the request uses break-glass mode
request.metadataobjectProvider-specificAdditional provider parameters (currently empty for built-in providers)

Package: jitsudo.eligibility

Output variableTypeDefaultDescription
allowbooleanfalseWhether the request is allowed to proceed to the approval queue
reasonstring""Human-readable explanation shown to the requester on denial

Evaluation semantics:

  • All enabled eligibility policies are evaluated.
  • The request proceeds if any policy returns allow = true.
  • The reason from the first denying policy (where allow = false) is shown to the requester.

Minimal policy:

package jitsudo.eligibility
default allow = false
default reason = "not authorized"
allow {
input.user.groups[_] == "sre"
}

Package: jitsudo.approval

Output variableTypeDefaultDescription
allowbooleanfalseWhether the request is approvable by the actor
reasonstring""Explanation if not approvable

Evaluation semantics:

  • All enabled approval policies are evaluated.
  • An approver action succeeds if any policy returns allow = true.

Minimal policy:

package jitsudo.approval
default allow = false
default reason = "requires SRE lead approval"
allow {
input.user.groups[_] == "sre-lead"
}

request.duration_seconds is an integer. Common conversions:

Human durationSeconds
15 minutes900
30 minutes1800
1 hour3600
2 hours7200
4 hours14400
8 hours28800
12 hours43200

Example policy that limits duration:

package jitsudo.eligibility
default allow = false
allow {
input.user.groups[_] == "sre"
input.request.duration_seconds <= 14400 # max 4 hours
}

request.metadata is a map<string, string> for provider-specific parameters. Currently empty for all built-in providers. Future providers may populate this field for provider-specific eligibility rules.

The following invariants hold for all requests reaching the policy engine:

  • user.email is non-empty (validated during token verification).
  • request.provider is one of aws, azure, gcp, kubernetes, mock.
  • request.role is non-empty.
  • request.duration_seconds is positive.
  • request.reason may be empty only if the server does not require it.

Use jitsudo policy eval to test policies against the live policy set:

Terminal window
jitsudo policy eval \
--type eligibility \
--input '{
"user": {"email": "alice@example.com", "groups": ["sre"]},
"request": {
"provider": "aws",
"role": "prod-infra-admin",
"resource_scope": "123456789012",
"duration_seconds": 7200,
"reason": "Test",
"break_glass": false,
"metadata": {}
}
}'

The response includes allowed, reason, and the full OPA result_json for debugging.

All standard OPA built-in functions are available, including:

  • String: startswith, endswith, contains, upper, lower
  • Time: time.now_ns(), time.weekday(), time.clock()
  • Sets and comprehensions: {x | ...}, count(), any(), all()
  • future.keywords for in, every, contains, if

See the OPA Policy Language documentation for the complete reference.