496303471d
---ci--- project: atelier phase: 7 milestone: v0.1 status: complete phase_role: final milestone_complete: true requirements: covered: [ATELIER-01, ATELIER-02, ATELIER-03, ATELIER-04, ATELIER-05, ATELIER-06, ATELIER-07, ATELIER-08, ATELIER-09, ATELIER-10, ATELIER-11, ATELIER-12, ATELIER-13, ATELIER-14, ATELIER-15, ATELIER-16, ATELIER-17, ATELIER-18, ATELIER-19, ATELIER-20, ATELIER-21, ATELIER-22, ATELIER-23, ATELIER-24, ATELIER-25, ATELIER-26, ATELIER-27, ATELIER-28, ATELIER-29, ATELIER-30, ATELIER-31, ATELIER-32, ATELIER-33, ATELIER-34, ATELIER-35] partial: [] ship: milestone: v0.1 type: NFR tag: v0.0.7 merge: milestone/v0.1-atelier -> main release: https://git.cloudinit.dev/cloudinit-bot/atelier/releases/tag/v0.0.7 ---/ci--- Milestone v0.1 — Initial Framework (NFR, complete). 8 core principles (C1-C8), 11 domains, 110 domain principles, 27 derived docs, 4 good + 3 bad examples, 4 language docs, full matrix, 3 review docs. All 35 requirements covered. 7 patches (v0.0.0 pre-execution through v0.0.7 final). v0.0.7 IS the v0.1.0 milestone release.
61 lines
2.7 KiB
Markdown
61 lines
2.7 KiB
Markdown
# Authorization — Derived Rules
|
|
|
|
> Derives from `domains/security/first-principles.md` P2 (Least Privilege), P3 (Defense in Depth), P1 (Zero Trust).
|
|
|
|
## The Default: Deny
|
|
|
|
- Every request is denied unless explicitly authorized.
|
|
- "Authorized by default" is an anti-pattern. The absence of a rule means denial.
|
|
- A missing authz check is a bug, not a feature gap.
|
|
|
|
## Authorization Models
|
|
|
|
### RBAC (Role-Based)
|
|
- Users have roles; roles have permissions.
|
|
- Roles are coarse: `admin`, `editor`, `viewer`. Permissions are fine: `post:create`, `post:delete`.
|
|
- Check permissions, not roles: `can(user, 'post:create')`, not `user.role === 'admin'`.
|
|
- Roles can change; permission checks are stable.
|
|
|
|
### ABAC (Attribute-Based)
|
|
- Authorization based on attributes of the user, resource, and context.
|
|
- More expressive: "user can edit a post if user.department == post.department and post.status == 'draft'".
|
|
- Use when RBAC is too coarse. Beware: complex ABAC is hard to audit.
|
|
|
|
### ReBAC (Relationship-Based)
|
|
- Authorization based on relationships (e.g., Zanzibel).
|
|
- "user:alice is editor of document:42" — check the relationship graph.
|
|
- Scales for fine-grained, resource-specific access (Google Docs-style).
|
|
|
|
## Where to Check (P4 Locality)
|
|
|
|
- Check at the boundary: the API endpoint, the resolver, the controller.
|
|
- Check at the data layer: defense in depth. A query that bypasses the controller still respects row-level security.
|
|
- Never check only in the UI. The UI is a convenience, not a security boundary.
|
|
|
|
## Principle of Least Privilege (P2)
|
|
|
|
- A token/role gets the minimum permissions to do its job.
|
|
- No "admin" role for daily work. Admin is for administration; daily work uses a scoped role.
|
|
- Service tokens are scoped to one service's resources, not "all resources."
|
|
|
|
## IDOR (Insecure Direct Object Reference) (P1 Zero Trust)
|
|
|
|
- `/api/users/123` — does the requester own 123? Check.
|
|
- Never assume the user can access any ID they request. The ID is input; inputs are untrusted.
|
|
- Use scoped queries: `User.find({ id, owner: userId })`, not `User.find(id)`.
|
|
|
|
## Caching and Authz (P3 Defense in Depth)
|
|
|
|
- Authorization is not cached across users. A cached response for user A is not served to user B.
|
|
- Cache keys include the user/role, not just the resource.
|
|
- "Cache it as public if anyone can see it" — only if truly anyone (no auth).
|
|
|
|
## What Violates Authorization
|
|
|
|
| Violation | Principle |
|
|
|-----------|-----------|
|
|
| `/admin` endpoint with no authz check | P1 Zero Trust |
|
|
| `user.role === 'admin'` instead of permission check | P2 (roles change) |
|
|
| IDOR: `User.find(req.params.id)` with no ownership check | P1 Zero Trust |
|
|
| Cached authz decision reused across users | P3 Defense in Depth |
|
|
| Service token with "all resources" scope | P2 Least Privilege | |