Skip to content

Cedar Authorization Information.

What is Cedar?

Cedar is a language for writing authorization policies.

It is included here ONLY as an example of how to model Authorization decision logic to server as a reference point for the Arda Multi-Enterprise Authorization Model.

The Documentation for Cedar is available at:

Cedar Concepts

uml diagram

Cedar Authorization Decision Logic

To formally describe the authorization decision that Cedar models, we can use a predicate logic approach. This captures the “default deny” and “forbid takes precedence” principles inherent in Cedar’s evaluation.

Let’s define the key components and predicates:

Given Inputs:

  • \(R\): An AuthorizationRequest (from the diagram) represented as a tuple \((P, A, Res, C, E)\), where:
    • \(P\) is the Principal entity.
    • \(A\) is the Action entity.
    • \(Res\) is the Resource entity.
    • \(C\) is the Context attributes.
    • \(E\) is the list of Entity objects (the comprehensive entity pool for relationships and attribute lookups).
  • \(PS\): A PolicySet (from the diagram) containing a collection of Policy objects.
  • \(S\): A Schema (from the diagram) used for policy and entity validation.

–Predefined Predicates (Primitives or Abstractions):–

  1. Validate(e: Entity, s: Schema) \rightarrow Boolean: Returns true if the structure and types of the entity e are consistent with the Schema s. This ensures data integrity and type safety before evaluation. This would apply to all entities in the request (\(P, A, Res\)) and those in the E pool.
  2. IsMemberOf(e: Entity, groupType: String, groupId: String, entities: List<Entity>) \rightarrow Boolean: Returns true if entity e is a direct or transitive member of the group identified by groupType and groupId within the entities pool. This models the in operator for hierarchical relationships.
  3. EvaluateExpression(expr: String, principal: Entity, action: Entity, resource: Entity, context: Context, entities: List<Entity}, schema: Schema) \rightarrow Boolean: Evaluates a Cedar expression string (from a Condition) within the given request context. This predicate encapsulates attribute lookup, operator evaluation, and type checking against the schema. It returns true or false based on the expression’s evaluation.

Core Evaluation Predicates:

  1. ScopeMatches(reqEntity: Entity, policyScope: Scope, entities: List<Entity>) \rightarrow Boolean:

    This predicate determines if a given entity from the AuthorizationRequest (reqEntity) matches the scope defined in a Policy (policyScope).

ScopeMatches(reqEntity, policyScope, entities) :=
    (policyScope.id == NULL AND policyScope.type == NULL) OR  -- Matches any entity (e.g., 'principal', 'action', 'resource' without specific type/ID)
    (
        reqEntity.type == policyScope.type
        AND
        (
            (policyScope.inOperator AND IsMemberOf(reqEntity, policyScope.type, policyScope.id, entities))
            OR
            (NOT policyScope.inOperator AND reqEntity.id == policyScope.id)
        )
    )
  1. IsConditionTrue(request: AuthorizationRequest, condition: Condition, entities: List<Entity>, schema: Schema) \rightarrow Boolean:

    This predicate checks if a Condition (either when or unless) evaluates to true for the given AuthorizationRequest.

  IsConditionTrue(request, condition, entities, schema) :=
      EvaluateExpression(condition.expression, request.principal, request.action, request.resource, request.context, entities, schema)
  1. IsApplicable(policy: Policy, request: AuthorizationRequest, entities: List<Entity>, schema: Schema) \rightarrow Boolean:

    A Policy is applicable to an AuthorizationRequest if all its scope clauses match and all its conditions (both when and unless) are met.

IsApplicable(policy, request, entities, schema) :=
    ScopeMatches(request.principal, policy.principalScope, entities)
    AND ScopeMatches(request.action, policy.actionScope, entities)
    AND ScopeMatches(request.resource, policy.resourceScope, entities)
    AND (FOR ALL w IN policy.whenClauses: IsConditionTrue(request, w, entities, schema))
    AND (FOR ALL u IN policy.unlessClauses: NOT IsConditionTrue(request, u, entities, schema))

Main Authorization Decision Predicate:

Finally, the top-level Authorize predicate determines the final AuthorizationDecision for a given AuthorizationRequest and PolicySet.

Authorize(request: AuthorizationRequest, policySet: PolicySet, schema: Schema) \rightarrow AuthorizationDecision :=
    (
        -- Ensure all entities in the request are valid according to the schema
        Validate(request.principal, schema)
        AND Validate(request.action, schema)
        AND Validate(request.resource, schema)
        AND (FOR ALL e IN request.entities: Validate(e, schema))
    )
    AND (
        LET is_permitted = EXISTS p IN policySet : (p.effect == permit AND IsApplicable(p, request, request.entities, schema))
        LET is_forbidden = EXISTS f IN policySet : (f.effect == forbid AND IsApplicable(f, request, request.entities, schema))
        IN
        (
            IF (is_permitted AND NOT is_forbidden) THEN
                AuthorizationDecision.decision == Allow
            ELSE
                AuthorizationDecision.decision == Deny
            END IF
        )
    )

Interpretation:

  • The authorization decision is Allow if and only if there is at least one permit policy in the PolicySet that is applicable to the request, AND there are no forbid policies in the PolicySet that are applicable to the request.
  • Otherwise, the decision is Deny (this reflects the “default deny” principle).
  • All entities involved in the request and in the entity pool must be valid according to the defined schema for the evaluation to proceed meaningfully.

Comments