You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: coderd/rbac/README.md
+87-3Lines changed: 87 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -102,18 +102,102 @@ Example of a scope for a workspace agent token, using an `allow_list` containing
102
102
}
103
103
```
104
104
105
+
##OPA (Open Policy Agent)
106
+
107
+
Open Policy Agent (OPA) is an open source tool used to define and enforce policies.
108
+
Policies are written in a high-level, declarative language called Rego. Coder’s RBAC rules are defined in the[`policy.rego`](policy.rego) file.
109
+
110
+
When OPA evaluates policies, it binds input data to a global variable called`input`.
111
+
In the`rbac` package, this structured data is defined as JSON and contains the subject, action, and object (see`regoInputValue` in[astvalue.go](astvalue.go)).
112
+
OPA evaluates whether the subject is allowed to perform the action on the object across three levels: site, org, and user.
113
+
This is determined by the final rule`allow`, defined in[`policy.rego`](policy.rego), which aggregates the results of multiple rules to decide if the user has the necessary permissions.
114
+
Similarly to the input, OPA produces structured output data, which includes the`allow` variable as part of the evaluation result.
115
+
Authorization succeeds only if`allow` explicitly evaluates to`true`. If no`allow` is returned, it is considered unauthorized.
116
+
To learn more about OPA and Rego, seehttps://www.openpolicyagent.org/docs.
117
+
118
+
###Application and Database Integration
119
+
120
+
-[`rbac/authz.go`](authz.go) – Application layer integration: provides the core authorization logic that integrates with Rego for policy evaluation.
121
+
-[`database/dbauthz/dbauthz.go`](../database/dbauthz/dbauthz.go) – Database layer integration: wraps the database layer with authorization checks to enforce access control.
122
+
123
+
There are two types of evaluation in OPA:
124
+
125
+
-**Full evaluation**: Produces a decision that can be enforced.
126
+
This is the default evaluation mode, where OPA evaluates the policy using`input` data that contains all known values and returns output data with the`allow` variable.
127
+
-**Partial evaluation**: Produces a new policy that can be evaluated later when the_unknowns_ become_known_.
128
+
This is an optimization in OPA where it evaluates as much of the policy as possible without resolving expressions that depend on_unknown_ values from the`input`.
129
+
To learn more about partial evaluation, see this[OPA blog post](https://blog.openpolicyagent.org/partial-evaluation-162750eaf422).
130
+
131
+
Application of Full and Partial evaluation in`rbac` package:
132
+
133
+
-**Full Evaluation** is handled by the`RegoAuthorizer.Authorize()` method in`authz.go`.
134
+
This method determines whether a subject (user) can perform a specific action on an object.
135
+
It performs a full evaluation of the Rego policy, which returns the`allow` variable to decide whether access is granted or denied (`true` or`false`, respectively).
136
+
-**Partial Evaluation** is handled by the`RegoAuthorizer.Prepare()` method in`authz.go`.
137
+
This method compiles Rego’s partial evaluation queries into`SQL WHERE` clauses.
138
+
These clauses are then used to enforce authorization directly in database queries, rather than in application code.
139
+
140
+
Authorization Patterns:
141
+
142
+
- Fetch-then-authorize: an object is first retrieved from the database, and a single authorization check is performed using full evaluation via`Authorize()`.
143
+
- Authorize-while-fetching: Partial evaluation via`Prepare()` is used to inject SQL filters directly into queries, allowing efficient authorization of many objects of the same type.
144
+
`dbauthz` methods that enforce authorization directly in the SQL query are prefixed with`Authorized`, for example,`GetAuthorizedWorkspaces`.
145
+
105
146
##Testing
106
147
107
-
You can test outside of golang by using the`opa` cli.
This command performs a partial evaluation of the policy, specifying a set of unknown input parameters.
172
+
The result is a set of partial queries that can be converted into`SQL WHERE` clauses and injected into SQL queries.
173
+
174
+
This command answers the question: “What conditions must be met for the user to be allowed?”
175
+
176
+
###Benchmarking
177
+
178
+
Benchmark tests to evaluate the performance of full and partial evaluation can be found in`authz_test.go`.
179
+
You can run these tests with the`-bench` flag, for example:
180
+
181
+
```bash
182
+
gotest -bench=BenchmarkRBACFilter -run=^$
183
+
```
184
+
185
+
To capture memory and CPU profiles, use the following flags:
186
+
187
+
-`-memprofile memprofile.out`
188
+
-`-cpuprofile cpuprofile.out`
189
+
190
+
The script[`benchmark_authz.sh`](./scripts/benchmark_authz.sh) runs the authz benchmark tests on the current Git branch or compares benchmark results between two branches using[`benchstat`](https://pkg.go.dev/golang.org/x/perf/cmd/benchstat).
191
+
`benchstat` compares the performance of a baseline benchmark against a new benchmark result and highlights any statistically significant differences.