intermediate30 min readgetting-startedUpdated: 2025-06-28

Cedar Policy Language Guide

Learn the fundamentals of Cedar, the high-performance policy language from AWS, for building secure and auditable application authorization.

📋 Prerequisites

  • Understanding of authorization concepts (principal, action, resource)
  • Familiarity with JSON data structures
  • A basic understanding of application security
  • Access to a command line/terminal

🎯 What You'll Learn

  • Cedar's core design principles: performance, safety, and analysis
  • The Principal, Action, Resource, Context (PARC) authorization model
  • How to write permit and forbid policies using Cedar's syntax
  • Using a schema to validate policies and prevent errors
  • How to test and evaluate policies using the Cedar CLI
  • How Cedar integrates with AWS Verified Permissions

🏷️ Topics Covered

cedar policy language tutorialaws cedar vs opa comparisonhow to write cedar policiescedar policy language examplesaws verified permissions cedar guidecedar policy language syntax

Cedar Policy Language Tutorial: AWS Verified Permissions Guide

Cedar is an open-source language for defining access control policies. Developed by AWS, it's designed to be ergonomic for developers, fast enough for critical authorization paths, and safe enough for security reviews. Unlike IAM, which governs access to AWS resources, Cedar is designed for developers to control access within their own applications.

It is the engine behind AWS Verified Permissions and is built on a simple but powerful model: "permit principals to perform actions on resources when specified conditions are met."

Human-Readable Policies

Cedar policies are designed to be intuitive and easy to read, resembling natural language sentences. This simplifies writing, reviewing, and auditing.

Schema-Based Validation

You can define a schema for your application's entities and attributes. Cedar's validator uses this schema to catch errors in your policies before they are ever evaluated.

Formal Verification

Cedar's design is backed by automated reasoning and formal verification, providing mathematical assurances about its behavior, such as "a deny policy always overrides a permit."

How to Write Cedar Policies: Syntax and Examples for Beginners

Cedar is built on two core concepts: the policy structure and the entity-attribute model.

The Policy Structure: permit and forbid

A Cedar policy either grants (permit) or denies (forbid) permission. The structure is straightforward:

basic-policy.cedar

// A 'permit' policy grants access
permit (
    principal,
    action,
    resource
)
when { // Optional conditions
    //...
}
unless { // Optional exceptions
    //...
};

// A 'forbid' policy explicitly denies access.
// It overrides any and all 'permit' policies.
forbid (
    principal,
    action,
    resource
);

Entities and Attributes

Everything in Cedar is an entity, which has a type and a unique ID (e.g., User::"alice"). Entities can also have attributes, which are key-value pairs (e.g., department: "finance").

🔧 Core Entity Types

  • Principal: The entity requesting to perform an action (e.g., a user, a service).
  • Action: The action the principal wants to perform (e.g., Action::"viewPhoto", Action::"deleteAlbum").
  • Resource: The entity being acted upon (e.g., a photo, a file).
  • Context: Optional request-time information, like the source IP address or time of day.

AWS Verified Permissions Cedar Guide: Step-by-Step Tutorial

Let's write policies for a simple photo-sharing application. First, we define a schema.

1

Define a Schema

The schema describes our application's entity types and the attributes they can have. This allows the Cedar validator to catch typos and other errors.

2

Write the Policies

Create authorization logic in a .cedar file using permit and forbid statements.

1. Define a Schema

photo_app_schema.json

{
    "PhotoApp": {
        "entityTypes": {
            "User": {
                "shape": {
                    "type": "Record",
                    "attributes": {
                        "department": {"type": "String"},
                        "jobLevel": {"type": "Long"}
                    }
                }
            },
            "Photo": {
                "shape": {
                    "type": "Record",
                    "attributes": {
                        "isPrivate": {"type": "Boolean"},
                        "owner": {"type": "Entity", "name": "User"},
                        "album": {"type": "Entity", "name": "Album"}
                    }
                }
            },
            "Album": {
                "memberOfTypes": ["User"]
            }
        },
        "actions": {
            "view": { "appliesTo": { "principalTypes": ["User"], "resourceTypes": ["Photo"] } },
            "delete": { "appliesTo": { "principalTypes": ["User"], "resourceTypes": ["Photo"] } }
        }
    }
}

2. Write the Policies

Now we write our authorization logic in a .cedar file.

policies.cedar

// Policy 1: Users can view their own photos.
permit(
    principal,
    action == Action::"view",
    resource
)
when {
    principal == resource.owner
};

// Policy 2: Users can view any photo in an album they are a member of.
permit(
    principal,
    action == Action::"view",
    resource
)
when {
    principal in resource.album
};

// Policy 3: Forbid viewing of private photos, unless the viewer is the owner.
// This is a powerful safety guardrail.
forbid(
    principal,
    action == Action::"view",
    resource
)
when {
    resource.isPrivate == true
}
unless {
    principal == resource.owner
};

// Policy 4: Users with job level 5 or higher can delete any photo.
permit(
    principal,
    action == Action::"delete",
    resource
)
when {
    principal.jobLevel >= 5
};

Cedar Policy Language Examples: Testing and Validation Best Practices

We can use the Cedar CLI to test our work. First, install the cedar-policy Rust crate.

Install Cedar CLI

cargo install cedar-policy-cli

1. Validate Policies Against the Schema

This command checks for correctness, such as ensuring we didn't misspell an attribute (e.g., resource.ownr instead of resource.owner).

Validate Policies

cedar validate --schema photo_app_schema.json --policies policies.cedar

2. Test an Authorization Request

Let's ask Cedar for a decision. We need to provide the request context and a file describing our entities (who owns what).

entities.json

[
    {
        "uid": {"type": "User", "id": "alice"},
        "attrs": {"department": "eng", "jobLevel": 6}
    },
    {
        "uid": {"type": "User", "id": "bob"},
        "attrs": {"department": "sales", "jobLevel": 3}
    },
    {
        "uid": {"type": "Album", "id": "vacation_pics"},
        "parents": [{"type": "User", "id": "bob"}]
    },
    {
        "uid": {"type": "Photo", "id": "photo123"},
        "attrs": {
            "isPrivate": true,
            "owner": {"type": "User", "id": "alice"},
            "album": {"type": "Album", "id": "vacation_pics"}
        }
    }
]

Now, let's see if Bob can view Alice's private photo (he shouldn't be able to).

Authorize Request

cedar authorize \
    --principal 'User::"bob"' \
    --action 'Action::"view"' \
    --resource 'Photo::"photo123"' \
    --policies policies.cedar \
    --entities entities.json

# OPA Response:
# DENY

The decision is DENY. Even though Bob is a member of the album (Policy 2), the forbid policy (Policy 3) for private photos takes precedence.

Cedar Policy Language Syntax: Production Best Practices Guide

📋

Schema First

Always start by defining a schema. It enables static validation that catches errors early and serves as clear documentation.

🛡️

Use forbid for Guardrails

Use permit policies to grant permissions broadly and forbid policies to create specific, non-negotiable security boundaries.

🎯

Attribute-Based Control (ABAC)

Leverage attributes on your principal and resource entities to create flexible policies that don't need to be updated when a new user or resource is added.

📐

Policy Templates

For recurring patterns, use policy templates. These are policies with placeholders (e.g., ?principal, ?resource) that can be instantiated with specific entities.

🎉 Congratulations!

Cedar Mastery Achieved

You have learned the core concepts of the Cedar policy language. You are now able to:

Understand Cedar's Design

Comprehend Cedar's safety-first design principles and formal verification approach.

Write Effective Policies

Create permit and forbid policies using entities and attributes effectively.

Validate with Schema

Use schemas to validate your policies and prevent common errors before deployment.

Test Authorization

Evaluate authorization requests to get reliable Allow or Deny decisions.

Next Steps