Skip to content

Commit 24c7c87

Browse files
Copilotmserico
andcommitted
Fix getImplicitPermissionsForUser to support wildcard domains in role hierarchies
Co-authored-by: mserico <[email protected]>
1 parent 9347b83 commit 24c7c87

File tree

4 files changed

+92
-1
lines changed

4 files changed

+92
-1
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act, dom
3+
4+
[policy_definition]
5+
p = sub, obj, act, dom
6+
7+
[role_definition]
8+
g = _, _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = (g(r.sub, p.sub, r.dom) || g(r.sub, p.sub, '*')) && (p.dom == '*' || r.dom == p.dom) && r.obj == p.obj && r.act == p.act
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
p, abstract_role1, devis, read, *
2+
p, abstract_role1, devis, create, *
3+
p, abstract_role2, devis, read, *
4+
p, abstract_role2, organization, read, *
5+
p, abstract_role2, organization, write, *
6+
7+
g, role1, abstract_role1, tenant1
8+
g, role1, abstract_role1, tenant2
9+
g, role1, abstract_role1, tenant3
10+
g, role2, abstract_role2, tenant1
11+
g, role2, abstract_role2, tenant2
12+
g, role2, abstract_role2, tenant3
13+
g, super_user, abstract_role2, *
14+
15+
g, michael, role1, tenant1
16+
g, antoine, role1, tenant2
17+
g, kevin, role1, tenant3
18+
g, thomas, role2, tenant1
19+
g, lucie, role2, tenant3
20+
g, theo, super_user, *

src/enforcer.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,13 +305,25 @@ export class Enforcer extends ManagementEnforcer {
305305
let n: string | undefined;
306306
while ((n = q.shift()) !== undefined) {
307307
for (const rm of this.rmMap.values()) {
308+
// Get roles for the specified domain
308309
const role = await rm.getRoles(n, ...domain);
309310
role.forEach((r) => {
310311
if (!res.has(r)) {
311312
res.add(r);
312313
q.push(r);
313314
}
314315
});
316+
317+
// Also check for roles with wildcard domain if a specific domain was provided
318+
if (domain && domain.length > 0 && domain[0] !== '*') {
319+
const wildcardRoles = await rm.getRoles(n, '*');
320+
wildcardRoles.forEach((r) => {
321+
if (!res.has(r)) {
322+
res.add(r);
323+
q.push(r);
324+
}
325+
});
326+
}
315327
}
316328
}
317329

@@ -337,7 +349,23 @@ export class Enforcer extends ManagementEnforcer {
337349

338350
for (const n of roles) {
339351
if (withDomain) {
340-
const p = await this.getFilteredPolicy(0, n, ...domain);
352+
// Get all policies for this role/user (filter by subject only)
353+
const allPolicies = await this.getFilteredPolicy(0, n);
354+
355+
// Get the domain field index from the model
356+
const domainIndex = this.model.getFieldIndex('p', FieldIndex.Domain);
357+
358+
// Filter policies to match the requested domain or wildcard domain
359+
const p = allPolicies.filter((policy) => {
360+
if (domainIndex === -1) {
361+
// No domain field in policy, use old behavior
362+
return domain.every((d, i) => policy[i + 1] === d);
363+
}
364+
// Check if policy domain matches requested domain or is wildcard
365+
const policyDomain = policy[domainIndex];
366+
return policyDomain === domain[0] || policyDomain === '*';
367+
});
368+
341369
res.push(...p);
342370
} else {
343371
const p = await this.getPermissionsForUser(n);

test/rbacAPI.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,32 @@ test('test rbac with multiple policy definitions', async () => {
219219
['admin', 'create'],
220220
]);
221221
});
222+
223+
test('test getImplicitPermissionsForUser with role hierarchy and wildcard domain', async () => {
224+
const e = await newEnforcer(
225+
'examples/rbac_with_hierarchy_with_wildcard_domain_model.conf',
226+
'examples/rbac_with_hierarchy_with_wildcard_domain_policy.csv'
227+
);
228+
229+
// Test user 'michael' who has role1 in tenant1
230+
// role1 inherits from abstract_role1 in tenant1
231+
// abstract_role1 has permissions with wildcard domain '*'
232+
const michaelPerms = await e.getImplicitPermissionsForUser('michael', 'tenant1');
233+
expect(michaelPerms).toContainEqual(['abstract_role1', 'devis', 'read', '*']);
234+
expect(michaelPerms).toContainEqual(['abstract_role1', 'devis', 'create', '*']);
235+
236+
// Test user 'thomas' who has role2 in tenant1
237+
// role2 inherits from abstract_role2 in tenant1
238+
// abstract_role2 has multiple permissions with wildcard domain '*'
239+
const thomasPerms = await e.getImplicitPermissionsForUser('thomas', 'tenant1');
240+
expect(thomasPerms).toContainEqual(['abstract_role2', 'devis', 'read', '*']);
241+
expect(thomasPerms).toContainEqual(['abstract_role2', 'organization', 'read', '*']);
242+
expect(thomasPerms).toContainEqual(['abstract_role2', 'organization', 'write', '*']);
243+
244+
// Test user 'theo' who has super_user role with wildcard domain
245+
// super_user inherits from abstract_role2 with wildcard domain '*'
246+
const theoPerms = await e.getImplicitPermissionsForUser('theo', 'any_tenant');
247+
expect(theoPerms).toContainEqual(['abstract_role2', 'devis', 'read', '*']);
248+
expect(theoPerms).toContainEqual(['abstract_role2', 'organization', 'read', '*']);
249+
expect(theoPerms).toContainEqual(['abstract_role2', 'organization', 'write', '*']);
250+
});

0 commit comments

Comments
 (0)