10 Policy as code: Effective authorization policies
The chapter introduces authorization policies as a critical, living part of system design rather than a minor technical detail. Through ACME’s dynamic authorization use cases, it explains that policies must be clear, consistent, least-privilege, and resilient to organizational change. It also emphasizes that good policy design depends on stable concepts such as projects, teams, and roles, rather than fragile details like titles, hard-coded names, or broad catch-all permissions.
It then frames policy as code as the practical way to manage authorization at scale. In this model, policies are authored, reviewed, versioned, and tested in repositories, then promoted as signed bundles into runtime policy stores for enforcement. Keeping repositories separate from stores creates a clean boundary between human-centered authoring and machine-centered execution, while schemas, validation, and code reviews help keep policy language consistent and prevent accidental drift.
Finally, the chapter shows how assurance comes from testing and static analysis. Realistic request-based tests confirm expected allows and denies, regression tests preserve fixes, and coverage ensures important rules are exercised. Static analysis complements testing by detecting conflicts, redundancies, and gaps before deployment. Together, these practices make authorization more transparent, safer to change, and reliable enough to support modern systems at scale.
Inconsistent vs. consistent scopes. In the first case, managers outside Project Alpha gain unintended access; in the second, access is controlled only by project membership.
Overly broad versus least-privilege scope. Giving all employees access to all documents exposed sensitive financial forecasts in Project Alpha. Restricting access to only project members enforces the principle of least privilege.
Hard-coded vs. data-driven policies. An employee can lose access when the policy checks department names directly but keeps access when the policy references durable roles from the HR system.
Bundled vs. fine-grained actions. In the bundled approach, both employees and customers can share documents; in the fine-grained approach, only employees can share documents, which gives ACME precise control while preserving ease of use.
Brittle vs. stable policies. A title check causes Dan to lose access after a promotion, while a team check maintains access because membership stays valid.
Continuous integration for policies. Bob’s pull request triggers validation, analysis, and testing. After the checks pass, his changes are merged, bundled into a signed package, and published to a policy store, where the authorizer uses them to evaluate requests at runtime.
Summary
- Effective policies are more than just one-off rules; they are design artifacts that must remain clear, consistent, and aligned with business needs over time.
- Clarity and consistency help prevent conflicts. At ACME, policies defined by project membership were more predictable than ad hoc rules based on organizational roles.
- Least privilege depends on precise scope. Limiting access by project, role, or relationship helps prevent overly broad permissions from exposing resources beyond their intended audience.
- Separating policy from data makes rules more stable. Policies that check durable roles or teams are better at surviving organizational change than those that use hard-coded department names or other data that is frequently updated.
- Granularity matters. Fine-grained actions such as view, edit, and share offer precision, while grouping them into higher-level roles in the UI keeps things simple.
- Policies tied to stable entities like teams or projects are resistant to change. An employee’s promotion might violate a title-based policy, for example, but wouldn’t affect one based on the employee’s team.
- Policy repositories and policy stores serve different functions. Repos are used for authoring, history, and review; stores are for runtime enforcement with signed, versioned bundles.
- Schemas ensure consistency. By validating policies against schemas, ACME avoided mismatched action names and discovered missing attributes before deployment.
- Versioning and review promote accountability. Pull requests record the reasoning for each policy change and enable reviewers to question scope and intent.
- Operational practices ensure policies are auditable. Decision logs, explainability, and rollback features provide developers and operators with visibility and control.
- Continuous integration links these practices. Every pull request triggers validation, analysis, and testing before bundles are published to policy stores.
- Testing is as essential for policies as it is for code. ACME employs unit, scenario, regression, and coverage tests to prevent regressions and confirm real-world behavior.
- Static analysis complements testing. Cedar Analysis inspects the policy set for conflicts, redundancies, and gaps, offering confidence that policies are sound and complete.
- Effective authorization relies on three key areas: principles that define good policies, policy-as-code practices that manage and deploy policies, and testing and analysis to ensure policies work as intended.
- Authorization policies should be treated as design artifacts, managed as code, and tested with the same rigor as software to function as a dependable foundation for dynamic authorization.
Authorization in Action ebook for free