Skip to content

Commit 813270d

Browse files
chore: bump github.com/open-policy-agent/opa from 0.70.0 to 1.0.0 (#16013)
Opting into rego v1. Rego v1 requires `if` for all rule statements. This PR updates the dependencies and the rego policy itself. Golang imports upgraded for opa/rego --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
1 parent 4495db8 commit 813270d

File tree

7 files changed

+127
-107
lines changed

7 files changed

+127
-107
lines changed

coderd/rbac/authz.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
"github.com/ammario/tlru"
1414
"github.com/open-policy-agent/opa/ast"
15-
"github.com/open-policy-agent/opa/rego"
15+
"github.com/open-policy-agent/opa/v1/rego"
1616
"github.com/prometheus/client_golang/prometheus"
1717
"github.com/prometheus/client_golang/prometheus/promauto"
1818
"go.opentelemetry.io/otel/attribute"

coderd/rbac/error.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import (
66
"flag"
77
"fmt"
88

9-
"github.com/open-policy-agent/opa/rego"
109
"github.com/open-policy-agent/opa/topdown"
10+
"github.com/open-policy-agent/opa/v1/rego"
1111
"golang.org/x/xerrors"
1212

1313
"github.com/coder/coder/v2/coderd/httpapi/httpapiconstraints"

coderd/rbac/policy.rego

Lines changed: 84 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package authz
2-
import future.keywords
2+
3+
import rego.v1
4+
35
# A great playground: https://play.openpolicyagent.org/
46
# Helpful cli commands to debug.
57
# opa eval --format=pretty 'data.authz.allow' -d policy.rego -i input.json
@@ -29,67 +31,74 @@ import future.keywords
2931

3032
# bool_flip lets you assign a value to an inverted bool.
3133
# You cannot do 'x := !false', but you can do 'x := bool_flip(false)'
32-
bool_flip(b) = flipped {
33-
b
34-
flipped = false
34+
bool_flip(b) := flipped if {
35+
b
36+
flipped = false
3537
}
3638

37-
bool_flip(b) = flipped {
38-
not b
39-
flipped = true
39+
bool_flip(b) := flipped if {
40+
not b
41+
flipped = true
4042
}
4143

4244
# number is a quick way to get a set of {true, false} and convert it to
4345
# -1: {false, true} or {false}
4446
# 0: {}
4547
# 1: {true}
46-
number(set) = c {
48+
number(set) := c if {
4749
count(set) == 0
48-
c := 0
50+
c := 0
4951
}
5052

51-
number(set) = c {
53+
number(set) := c if {
5254
false in set
53-
c := -1
55+
c := -1
5456
}
5557

56-
number(set) = c {
58+
number(set) := c if {
5759
not false in set
5860
set[_]
59-
c := 1
61+
c := 1
6062
}
6163

6264
# site, org, and user rules are all similar. Each rule should return a number
6365
# from [-1, 1]. The number corresponds to "negative", "abstain", and "positive"
6466
# for the given level. See the 'allow' rules for how these numbers are used.
65-
default site = 0
67+
default site := 0
68+
6669
site := site_allow(input.subject.roles)
70+
6771
default scope_site := 0
72+
6873
scope_site := site_allow([input.subject.scope])
6974

70-
site_allow(roles) := num {
75+
site_allow(roles) := num if {
7176
# allow is a set of boolean values without duplicates.
72-
allow := { x |
77+
allow := {x |
7378
# Iterate over all site permissions in all roles
74-
perm := roles[_].site[_]
75-
perm.action in [input.action, "*"]
79+
perm := roles[_].site[_]
80+
perm.action in [input.action, "*"]
7681
perm.resource_type in [input.object.type, "*"]
82+
7783
# x is either 'true' or 'false' if a matching permission exists.
78-
x := bool_flip(perm.negate)
79-
}
80-
num := number(allow)
84+
x := bool_flip(perm.negate)
85+
}
86+
num := number(allow)
8187
}
8288

8389
# org_members is the list of organizations the actor is apart of.
84-
org_members := { orgID |
90+
org_members := {orgID |
8591
input.subject.roles[_].org[orgID]
8692
}
8793

8894
# org is the same as 'site' except we need to iterate over each organization
8995
# that the actor is a member of.
90-
default org = 0
96+
default org := 0
97+
9198
org := org_allow(input.subject.roles)
99+
92100
default scope_org := 0
101+
93102
scope_org := org_allow([input.scope])
94103

95104
# org_allow_set is a helper function that iterates over all orgs that the actor
@@ -102,10 +111,10 @@ scope_org := org_allow([input.scope])
102111
# The reason we calculate this for all orgs, and not just the input.object.org_owner
103112
# is that sometimes the input.object.org_owner is unknown. In those cases
104113
# we have a list of org_ids that can we use in a SQL 'WHERE' clause.
105-
org_allow_set(roles) := allow_set {
106-
allow_set := { id: num |
114+
org_allow_set(roles) := allow_set if {
115+
allow_set := {id: num |
107116
id := org_members[_]
108-
set := { x |
117+
set := {x |
109118
perm := roles[_].org[id][_]
110119
perm.action in [input.action, "*"]
111120
perm.resource_type in [input.object.type, "*"]
@@ -115,7 +124,7 @@ org_allow_set(roles) := allow_set {
115124
}
116125
}
117126

118-
org_allow(roles) := num {
127+
org_allow(roles) := num if {
119128
# If the object has "any_org" set to true, then use the other
120129
# org_allow block.
121130
not input.object.any_org
@@ -135,78 +144,82 @@ org_allow(roles) := num {
135144
# This is useful for UI elements when we want to conclude, "Can the user create
136145
# a new template in any organization?"
137146
# It is easier than iterating over every organization the user is apart of.
138-
org_allow(roles) := num {
147+
org_allow(roles) := num if {
139148
input.object.any_org # if this is false, this code block is not used
140149
allow := org_allow_set(roles)
141150

142-
143151
# allow is a map of {"<org_id>": <number>}. We only care about values
144152
# that are 1, and ignore the rest.
145153
num := number([
146-
keep |
147-
# for every value in the mapping
148-
value := allow[_]
149-
# only keep values > 0.
150-
# 1 = allow, 0 = abstain, -1 = deny
151-
# We only need 1 explicit allow to allow the action.
152-
# deny's and abstains are intentionally ignored.
153-
value > 0
154-
# result set is a set of [true,false,...]
155-
# which "number()" will convert to a number.
156-
keep := true
154+
keep |
155+
# for every value in the mapping
156+
value := allow[_]
157+
158+
# only keep values > 0.
159+
# 1 = allow, 0 = abstain, -1 = deny
160+
# We only need 1 explicit allow to allow the action.
161+
# deny's and abstains are intentionally ignored.
162+
value > 0
163+
164+
# result set is a set of [true,false,...]
165+
# which "number()" will convert to a number.
166+
keep := true
157167
])
158168
}
159169

160170
# 'org_mem' is set to true if the user is an org member
161171
# If 'any_org' is set to true, use the other block to determine org membership.
162-
org_mem := true {
172+
org_mem if {
163173
not input.object.any_org
164174
input.object.org_owner != ""
165175
input.object.org_owner in org_members
166176
}
167177

168-
org_mem := true {
178+
org_mem if {
169179
input.object.any_org
170180
count(org_members) > 0
171181
}
172182

173-
org_ok {
183+
org_ok if {
174184
org_mem
175185
}
176186

177187
# If the object has no organization, then the user is also considered part of
178188
# the non-existent org.
179-
org_ok {
189+
org_ok if {
180190
input.object.org_owner == ""
181191
not input.object.any_org
182192
}
183193

184194
# User is the same as the site, except it only applies if the user owns the object and
185195
# the user is apart of the org (if the object has an org).
186-
default user = 0
196+
default user := 0
197+
187198
user := user_allow(input.subject.roles)
199+
188200
default user_scope := 0
201+
189202
scope_user := user_allow([input.scope])
190203

191-
user_allow(roles) := num {
192-
input.object.owner != ""
193-
input.subject.id = input.object.owner
194-
allow := { x |
195-
perm := roles[_].user[_]
196-
perm.action in [input.action, "*"]
204+
user_allow(roles) := num if {
205+
input.object.owner != ""
206+
input.subject.id = input.object.owner
207+
allow := {x |
208+
perm := roles[_].user[_]
209+
perm.action in [input.action, "*"]
197210
perm.resource_type in [input.object.type, "*"]
198-
x := bool_flip(perm.negate)
199-
}
200-
num := number(allow)
211+
x := bool_flip(perm.negate)
212+
}
213+
num := number(allow)
201214
}
202215

203216
# Scope allow_list is a list of resource IDs explicitly allowed by the scope.
204217
# If the list is '*', then all resources are allowed.
205-
scope_allow_list {
218+
scope_allow_list if {
206219
"*" in input.subject.scope.allow_list
207220
}
208221

209-
scope_allow_list {
222+
scope_allow_list if {
210223
# If the wildcard is listed in the allow_list, we do not care about the
211224
# object.id. This line is included to prevent partial compilations from
212225
# ever needing to include the object.id.
@@ -226,66 +239,70 @@ scope_allow_list {
226239
# Allow query:
227240
# data.authz.role_allow = true data.authz.scope_allow = true
228241

229-
role_allow {
242+
role_allow if {
230243
site = 1
231244
}
232245

233-
role_allow {
246+
role_allow if {
234247
not site = -1
235248
org = 1
236249
}
237250

238-
role_allow {
251+
role_allow if {
239252
not site = -1
240253
not org = -1
254+
241255
# If we are not a member of an org, and the object has an org, then we are
242256
# not authorized. This is an "implied -1" for not being in the org.
243257
org_ok
244258
user = 1
245259
}
246260

247-
scope_allow {
261+
scope_allow if {
248262
scope_allow_list
249263
scope_site = 1
250264
}
251265

252-
scope_allow {
266+
scope_allow if {
253267
scope_allow_list
254268
not scope_site = -1
255269
scope_org = 1
256270
}
257271

258-
scope_allow {
272+
scope_allow if {
259273
scope_allow_list
260274
not scope_site = -1
261275
not scope_org = -1
276+
262277
# If we are not a member of an org, and the object has an org, then we are
263278
# not authorized. This is an "implied -1" for not being in the org.
264279
org_ok
265280
scope_user = 1
266281
}
267282

268283
# ACL for users
269-
acl_allow {
284+
acl_allow if {
270285
# Should you have to be a member of the org too?
271286
perms := input.object.acl_user_list[input.subject.id]
287+
272288
# Either the input action or wildcard
273289
[input.action, "*"][_] in perms
274290
}
275291

276292
# ACL for groups
277-
acl_allow {
293+
acl_allow if {
278294
# If there is no organization owner, the object cannot be owned by an
279295
# org_scoped team.
280296
org_mem
281297
group := input.subject.groups[_]
282298
perms := input.object.acl_group_list[group]
299+
283300
# Either the input action or wildcard
284301
[input.action, "*"][_] in perms
285302
}
286303

287304
# ACL for 'all_users' special group
288-
acl_allow {
305+
acl_allow if {
289306
org_mem
290307
perms := input.object.acl_group_list[input.object.org_owner]
291308
[input.action, "*"][_] in perms
@@ -296,13 +313,13 @@ acl_allow {
296313
# The role or the ACL must allow the action. Scopes can be used to limit,
297314
# so scope_allow must always be true.
298315

299-
allow {
316+
allow if {
300317
role_allow
301318
scope_allow
302319
}
303320

304321
# ACL list must also have the scope_allow to pass
305-
allow {
322+
allow if {
306323
acl_allow
307324
scope_allow
308325
}

coderd/rbac/regosql/compile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"strings"
66

77
"github.com/open-policy-agent/opa/ast"
8-
"github.com/open-policy-agent/opa/rego"
8+
"github.com/open-policy-agent/opa/v1/rego"
99
"golang.org/x/xerrors"
1010

1111
"github.com/coder/coder/v2/coderd/rbac/regosql/sqltypes"

coderd/rbac/regosql/compile_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import (
44
"testing"
55

66
"github.com/open-policy-agent/opa/ast"
7-
"github.com/open-policy-agent/opa/rego"
7+
"github.com/open-policy-agent/opa/v1/rego"
88
"github.com/stretchr/testify/require"
99

1010
"github.com/coder/coder/v2/coderd/rbac/regosql"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy