Creating Your First Policy
Creating Your First Policy
Step-by-step guide to creating your first Cedar policy.
Why Policies Matter
By default, ZIRI denies all requests. You need at least one policy that permits requests, otherwise users can’t make any LLM calls.
Step 1: Understand What You Need
Before creating a policy, decide:
- Who should have access? (all users, specific departments, etc.)
- What actions? (completion, embedding, image_generation)
- Any restrictions? (time, IP, spend limits, models)
Step 2: Start Simple
Begin with a simple policy that allows completions for active keys:
policy.cedar
@id("allow-completion-active-keys")
permit (
principal,
action == Action::"completion",
resource
)
when {
principal.status == "active"
};This allows any active user key to make completion requests.
Step 3: Create the Policy
Via UI
- Go to Rules page
- Click Create Rule
- Paste the policy text
- Add description: “Allow completions for active keys”
- Click Create
Via API
curl -X POST http://localhost:3100/api/policies \
-H "Authorization: Bearer your-token" \
-H "Content-Type: application/json" \
-d '{
"policy": "@id(\"allow-completion-active-keys\") permit (principal, action == Action::\"completion\", resource) when { principal.status == \"active\" };",
"description": "Allow completions for active keys"
}'Step 4: Test the Policy
Make a test request:
curl -X POST http://localhost:3100/api/chat/completions \
-H "Content-Type: application/json" \
-H "X-API-Key: ziri-user-123-a1b2c3d4e5f67890" \
-d '{
"provider": "openai",
"model": "gpt-4o-mini",
"messages": [
{"role": "user", "content": "Hello!"}
]
}'If authorized, you’ll get a response. If denied, check the error message.
Step 5: Check Audit Logs
- Go to Logs page
- Find your request
- Check the decision and diagnostics
Step 6: Refine the Policy
Add restrictions as needed:
Add Tenant Restriction
permit (
principal,
action == Action::"completion",
resource
)
when {
principal.status == "active" &&
principal.user.tenant == "engineering"
};Add Spend Limit
permit (
principal,
action == Action::"completion",
resource
)
when {
principal.status == "active" &&
principal.current_daily_spend.lessThan(decimal("100.0"))
};Add Time Restriction
permit (
principal,
action == Action::"completion",
resource
)
when {
principal.status == "active" &&
context.hour >= 9 &&
context.hour < 18
};Common Mistakes
Forgetting Status Check
Always check principal.status == "active":
// Bad - allows revoked keys
permit (principal, action, resource);
// Good - only active keys
permit (principal, action, resource)
when { principal.status == "active" };Wrong Action Name
// Bad
action == "chat"
// Good
action == Action::"completion"Wrong Decimal Format
// Bad
principal.current_daily_spend < 100.0
// Good
principal.current_daily_spend.lessThan(decimal("100.0"))Missing Quotes
// Bad
principal.user.tenant == engineering
// Good
principal.user.tenant == "engineering"Using Templates
- Go to Rules page
- Click Templates
- Browse templates
- Click Use this template
- Modify as needed
- Save
Templates are pre-written policies you can customize.
Testing Policies
- Create the policy
- Make a test request
- Check audit logs
- Verify the decision matches expectations
- Adjust policy if needed