Skip to content

Commit 1d4492a

Browse files
committed
chore: update authz docs to clarify dif between v1
Signed-off-by: Mark Phelps <[email protected]>
1 parent 319590b commit 1d4492a

File tree

1 file changed

+237
-0
lines changed

1 file changed

+237
-0
lines changed

v2/configuration/authorization.mdx

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ title: Authorization
33
description: This document describes how to configure the authorization mechanisms for Flipt v2.
44
---
55

6+
Flipt v2 introduces an enhanced authorization system that provides environment-aware, hierarchical access control. This system builds upon v1's foundation while adding support for multi-environment deployments.
7+
68
Flipt supports the ability to secure its core API routes by setting the `required` field to `true` on the `authorization` configuration object.
79

810
```yaml config.yaml
@@ -51,6 +53,12 @@ The policy **must** have the following package declaration:
5153
package flipt.authz.v2
5254
```
5355

56+
<Note>
57+
Flipt v2 uses `package flipt.authz.v2` instead of v1's `package
58+
flipt.authz.v1`. This is a breaking change that reflects the enhanced
59+
authorization model.
60+
</Note>
61+
5462
#### Polling Interval
5563

5664
Flipt will poll the policy file for changes at a regular interval. By default, Flipt will poll the policy file every 5 minutes. You can adjust this interval by setting the `poll_interval` field in the `policy` object.
@@ -92,3 +100,232 @@ authorization:
92100
path: "data.json"
93101
poll_interval: "1m"
94102
```
103+
104+
## Key Differences from v1
105+
106+
Flipt v2 authorization introduces several important changes:
107+
108+
### 1. Environment-Aware Authorization
109+
110+
Unlike v1, which operates at the namespace level, v2 introduces a hierarchical model with environments:
111+
112+
- **Global scope**: Full access to all environments and namespaces
113+
- **Environment scope**: Manage namespaces within specific environments
114+
- **Namespace scope**: Manage resources (flags, segments, etc.) within specific namespaces
115+
116+
### 2. Optional Policy Queries for UI Filtering
117+
118+
v2 policies can optionally implement two special queries to enable UI filtering. When implemented, these queries allow the Flipt UI to show only the environments and namespaces that users have access to:
119+
120+
```rego
121+
# Returns list of environments the user can access
122+
viewable_environments := ["production", "staging"] # or ["*"] for all
123+
124+
# Returns list of namespaces in an environment the user can access
125+
viewable_namespaces(env) := ["frontend", "backend"] # or ["*"] for all
126+
```
127+
128+
<Note>
129+
These queries are **optional**. If not implemented, the UI will show all
130+
environments and namespaces, but authorization will still be enforced when
131+
users attempt to access them.
132+
133+
Implementing these queries improves the user
134+
experience by filtering out inaccessible resources in the UI.
135+
136+
</Note>
137+
138+
### 3. Simplified Request Structure
139+
140+
v2 uses a simplified request structure with `scope` field:
141+
142+
```json
143+
{
144+
"request": {
145+
"scope": "namespace", // or "environment"
146+
"environment": "production",
147+
"namespace": "frontend",
148+
"action": "update"
149+
}
150+
}
151+
```
152+
153+
## Example Policies
154+
155+
### Basic RBAC Policy
156+
157+
Here's a complete example of a v2 RBAC policy:
158+
159+
```rego policy.rego
160+
package flipt.authz.v2
161+
162+
import rego.v1
163+
164+
# Default deny
165+
default allow := false
166+
default viewable_environments := []
167+
168+
# Helper to get user/group identifiers
169+
subject_ids contains id if {
170+
user := input.authentication.metadata["io.flipt.auth.user"]
171+
id := sprintf("user:%s", [user])
172+
}
173+
174+
subject_ids contains id if {
175+
groups := input.authentication.metadata["io.flipt.auth.groups"]
176+
id := sprintf("group:%s", [groups[_]])
177+
}
178+
179+
# Check for global admin access
180+
has_global_access if {
181+
some binding in data.role_bindings
182+
binding.scope.type == "global"
183+
some subject in binding.subjects
184+
some id in subject_ids
185+
subject == id
186+
}
187+
188+
# Environment visibility
189+
viewable_environments := ["*"] if {
190+
has_global_access
191+
} else := envs if {
192+
envs := {env |
193+
some binding in data.role_bindings
194+
some subject in binding.subjects
195+
some id in subject_ids
196+
subject == id
197+
some b in binding.scope.bindings
198+
env := b.environment
199+
}
200+
}
201+
202+
# Namespace visibility within an environment
203+
viewable_namespaces(env) := ["*"] if {
204+
has_global_access
205+
} else := ["*"] if {
206+
# Check for wildcard namespace access
207+
some binding in data.role_bindings
208+
some subject in binding.subjects
209+
some id in subject_ids
210+
subject == id
211+
some b in binding.scope.bindings
212+
b.environment == env
213+
"*" in b.namespaces
214+
} else := namespaces if {
215+
# Return specific namespaces
216+
namespaces := {ns |
217+
some binding in data.role_bindings
218+
some subject in binding.subjects
219+
some id in subject_ids
220+
subject == id
221+
some b in binding.scope.bindings
222+
b.environment == env
223+
some ns in b.namespaces
224+
ns != "*"
225+
}
226+
}
227+
228+
# Main authorization logic
229+
allow if {
230+
has_global_access
231+
}
232+
233+
allow if {
234+
scope := input.request.scope
235+
env := input.request.environment
236+
ns := input.request.namespace
237+
action := input.request.action
238+
239+
# Check permissions based on scope
240+
some binding in data.role_bindings
241+
some subject in binding.subjects
242+
some id in subject_ids
243+
subject == id
244+
245+
some b in binding.scope.bindings
246+
b.environment == env
247+
248+
# Check namespace access
249+
ns in b.namespaces
250+
251+
# Check action permission
252+
action in b.permissions
253+
}
254+
```
255+
256+
### Example Data Structure
257+
258+
The accompanying `data.json` file defines role bindings:
259+
260+
```json data.json
261+
{
262+
"role_bindings": [
263+
{
264+
"role": "admin",
265+
"subjects": ["user:[email protected]"],
266+
"scope": {
267+
"type": "global"
268+
}
269+
},
270+
{
271+
"role": "platform_team",
272+
"subjects": ["group:platform"],
273+
"scope": {
274+
"type": "environment",
275+
"bindings": [
276+
{
277+
"environment": "production",
278+
"namespaces": ["*"],
279+
"permissions": ["*"]
280+
},
281+
{
282+
"environment": "staging",
283+
"namespaces": ["*"],
284+
"permissions": ["read", "update"]
285+
}
286+
]
287+
}
288+
},
289+
{
290+
"role": "developer",
291+
"subjects": ["user:[email protected]", "group:developers"],
292+
"scope": {
293+
"type": "namespace",
294+
"bindings": [
295+
{
296+
"environment": "development",
297+
"namespaces": ["frontend", "backend"],
298+
"permissions": ["*"]
299+
},
300+
{
301+
"environment": "staging",
302+
"namespaces": ["frontend"],
303+
"permissions": ["read"]
304+
}
305+
]
306+
}
307+
}
308+
]
309+
}
310+
```
311+
312+
This structure allows:
313+
314+
- **Global admins**: Full access to everything
315+
- **Platform team**: Manage all namespaces in production, read/update in staging
316+
- **Developers**: Full access to specific namespaces in development, read-only in staging
317+
318+
## Migration from v1
319+
320+
When migrating from v1 to v2:
321+
322+
1. **Update package declaration** from `flipt.authz.v1` to `flipt.authz.v2`
323+
2. **Add environment context** to your role bindings
324+
3. **Optionally implement the UI filtering queries**: `viewable_environments` and `viewable_namespaces(env)` for better UX
325+
4. **Update request handling** to use the new `scope` field instead of `resource`/`subject`
326+
5. **Remove bundle configurations** as they're not supported in v2 (yet)
327+
328+
<Warning>
329+
Existing v1 policies will not work without modification. Plan your migration
330+
carefully and test thoroughly before deploying to production.
331+
</Warning>

0 commit comments

Comments
 (0)