Cedar#
Cedar is a policy language and engine. CedarAuthorizer evaluates
Cedar policies in your process with cedarpy, Cedar’s Python bindings, so there is no policy service
to run or reach.
pip install "wardowl[cedar]"
from wardowl import PermissionedRetriever
from wardowl.authorizers.cedar import CedarAuthorizer
POLICIES = """
permit (principal, action == Action::"read", resource)
when { resource has allowed_users && resource.allowed_users.contains(principal.id) };
permit (principal, action == Action::"read", resource)
when { resource has allowed_groups && resource.allowed_groups.containsAny(principal.groups) };
"""
retriever = PermissionedRetriever(backend, CedarAuthorizer(POLICIES))
What a policy sees#
Cedar |
wardowl |
|---|---|
|
|
|
|
|
|
The entity types can be renamed with principal_type, group_type and resource_type, and
schema passes a Cedar schema for Cedar to validate against.
Hierarchies come from entities, a list of Cedar entities or a function of the subject that returns
them. For example, with payroll inside finance, principal in Group::"finance" holds for a member of
payroll:
payroll = {
"uid": {"__entity": {"type": "Group", "id": "payroll"}},
"attrs": {},
"parents": [{"__entity": {"type": "Group", "id": "finance"}}],
}
authorizer = CedarAuthorizer(POLICIES, entities=[payroll])
How it fails#
No pre-filter.
filter_forreturns None, so the retriever post-filters: every candidate is decided by Cedar, which is exact but searches more for users who may read little. Cedar’s partial evaluation, which could produce pre-filters, is experimental upstream.Errors deny. Cedar skips a policy whose evaluation errors, for example on a missing attribute, and that includes a
forbid. wardowl therefore denies any chunk whose evaluation reported an error, and logs how many on thewardowllogger. Guard optional attributes withhas.Values Cedar cannot hold are never left out. Cedar has strings, booleans, 64-bit integers (Long), sets and records. Integers, and floats with no fractional part (
3.0, from a store that returns every number as a float), become Longs. A chunk whose metadata holds any other value (a float such as2.5, None, an integer beyond 64 bits, or a list or record holding one) is denied without asking Cedar, and counted with the errors in the log: left out, the attribute would makeresource has xfalse and aforbidguarded by it would stop applying. A subject attribute of that kind raisesAuthorizationError. Store absent values as absent keys, not None, and numbers that need a fraction as strings or scaled integers.Keys Cedar cannot hold are treated the same way. A key that is not a string (JSON would write
1as"1"), or that is__entity,__extnor__expr, which Cedar’s JSON reserves for its escapes (a record holding one could be read as an entity reference or an extension value), denies the chunk wherever it appears in the metadata, and raisesAuthorizationErrorin a subject’s attributes. Other keys that start with__, such as__restricted, reach Cedar like any other: writeresource has "__restricted"in a policy, and declare them in aschemaif you pass one.Configuration is checked when the authorizer is created: policies Cedar cannot parse raise
ValueError. Any other failure raisesAuthorizationError, and the retriever returns nothing.