Skip to content

Commit 3b4bdc5

Browse files
authored
Merge pull request #5 from forths/master
新增获取角色下所有关联权限的功能
2 parents f64cb62 + b2d48bc commit 3b4bdc5

File tree

3 files changed

+54
-30
lines changed

3 files changed

+54
-30
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ RBAC python implementation based on Keycloak
5050

5151
* [x] 角色和权限关联
5252
* [x] 取消角色和权限关联
53-
* [ ] 获取角色的权限
53+
* [x] 获取角色的权限
5454
* [x] 获取权限关联的角色
5555

5656
## 用户和角色

demos/admindemo.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
sys.path.append(pwd.replace('/demos', ''))
55
from pyKeyCloakRBAC.pyrbac import PyRBACAdmin
66

7-
# 配置是否需要测试
8-
testdict = {'roletest': False, 'usertest': False, 'resourcetest': False,
9-
'permissiontest': False, 'policytest': False, 'user_role': False,
7+
# 配置是否需要演示
8+
testdict = {'roletest': True, 'usertest': True, 'resourcetest': True,
9+
'permissiontest': True, 'policytest': True, 'user_role': True,
1010
'role_permission': True}
1111

1212
if __name__ == '__main__':
13-
server_url = "http://xxxx:xxxx/auth/"
13+
# keycloak实际地址
14+
server_url = "http://host:port/auth/"
1415
# 管理员操作
1516
username = "realmadmin"
1617
password = "1111"
@@ -75,8 +76,8 @@
7576
new_info = {'emailVerified': True, 'attributes': {'count': ['999']}}
7677
print('\t', pa.update_user(uid, new_info))
7778
print('\t', pa.get_user(uid))
78-
print('删除用户 {}'.format(username))
79-
print('\t', pa.delete_user(uid))
79+
# print('删除用户 {}'.format(username))
80+
# print('\t', pa.delete_user(uid))
8081

8182
# 操作用户和角色
8283
if testdict['user_role']:
@@ -109,5 +110,7 @@
109110
print("\t", pa.op_permission_with_role(resource_client, resource, rolename))
110111
print('获取权限{}关联的角色:'.format(resource))
111112
print('\t', pa.get_permission_roles(resource_client, resource))
112-
print('角色{}取消权限{}: '.format(rolename, resource))
113-
print("\t", pa.op_permission_with_role(resource_client, resource, rolename, op="delete"))
113+
# print('角色{}取消权限{}: '.format(rolename, resource))
114+
# print("\t", pa.op_permission_with_role(resource_client, resource, rolename, op="delete"))
115+
print('获取角色{}的所有权限: '.format(rolename))
116+
print("\t", pa.get_role_permissions(resource_client, rolename))

pyKeyCloakRBAC/pyrbac.py

+42-21
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,26 @@ def get_client_policies(self, client_id):
6464
"cid": self.get_client_id(client_id)}
6565
data_raw = self.raw_get(url.format(**params_path))
6666
return raise_error_from_response(data_raw, KeycloakGetError)
67-
67+
6868
def create_policy(self, client_id, policyname, rolename):
6969
try:
7070
rid = self.get_role_id(rolename)
7171
payload = {"type": "role", "logic": "POSITIVE",
72-
"decisionStrategy": "UNANIMOUS", "name": policyname, "roles": [{"id": rid}]}
72+
"decisionStrategy": "AFFIRMATIVE", "name": policyname, "roles": [{"id": rid}]}
7373
cid = self.get_client_id(client_id)
7474
url = "admin/realms/{realm-name}/clients/{cid}/authz/resource-server/policy/role"
7575
params_path = {"realm-name": self.realm_name, "cid": cid}
7676
data_raw = self.raw_post(url.format(**params_path),
77-
data=json.dumps(payload))
77+
data=json.dumps(payload))
7878
return raise_error_from_response(data_raw, KeycloakGetError)
7979
except Exception as e:
8080
return self.errormsg(str(e))
8181

8282
def delete_policy(self, client_id, policyname):
8383
try:
8484
url = 'admin/realms/{realm-name}/clients/{cid}/authz/resource-server/policy/{pid}'
85-
params_path = {"realm-name": self.realm_name, "cid": self.get_client_id(client_id), 'pid': self.get_policy_id(client_id, policyname)}
85+
params_path = {"realm-name": self.realm_name, "cid": self.get_client_id(
86+
client_id), 'pid': self.get_policy_id(client_id, policyname)}
8687
rawdata = self.raw_delete(url.format(**params_path))
8788
return raise_error_from_response(rawdata, KeycloakGetError)
8889
except Exception as e:
@@ -105,7 +106,7 @@ def create_client_permission(self, client_id, resource):
105106
try:
106107
cid = self.get_client_id(client_id)
107108
url = "admin/realms/{realm-name}/clients/{cid}/authz/resource-server/permission/resource"
108-
payload = {"type": "resource", "logic": "POSITIVE", "decisionStrategy": "UNANIMOUS",
109+
payload = {"type": "resource", "logic": "POSITIVE", "decisionStrategy": "AFFIRMATIVE",
109110
"name": resource, "resources": [self.get_resource_id(client_id, resource)], "policies": []}
110111
params_path = {"realm-name": self.realm_name, "cid": cid}
111112
data_raw = self.raw_post(url.format(
@@ -120,7 +121,8 @@ def get_resources(self, client_id):
120121

121122
def get_resource_id(self, client_id, resourcename):
122123
url = "admin/realms/{realm-name}/clients/{cid}/authz/resource-server/resource/search?name={rn}"
123-
params_path = {'realm-name':self.realm_name, 'cid': self.get_client_id(client_id), 'rn': resourcename}
124+
params_path = {'realm-name': self.realm_name,
125+
'cid': self.get_client_id(client_id), 'rn': resourcename}
124126
raw_data = self.raw_get(url.format(**params_path))
125127
if raw_data.status_code == 200:
126128
return raw_data.json()['_id']
@@ -134,20 +136,29 @@ def get_permissions(self, client_id, permission=None):
134136
params_path = {"realm-name": self.realm_name, "cid": cid}
135137
else:
136138
url = 'admin/realms/{realm-name}/clients/{cid}/authz/resource-server/policy/search?name={pname}'
137-
params_path = {'realm-name': self.realm_name, 'cid': cid, 'pname':permission}
139+
params_path = {'realm-name': self.realm_name,
140+
'cid': cid, 'pname': permission}
138141
raw_data = self.raw_get(url.format(**params_path))
139142
return raise_error_from_response(raw_data, KeycloakGetError)
140143

144+
def delete_permission(self, client_id, permission):
145+
url = 'admin/realms/{realm-admin}/clients/{cid}/authz/resource-server/permission/{pid}'
146+
params_path = {'realm-name': self.realm_name, 'cid': self.get_client_id(
147+
client_id), 'pid': self.get_permissions(client_id, permission)['id']}
148+
raw_data = self.raw_delete(url.format(**params_path))
149+
return raise_error_from_response(raw_data, KeycloakGetError)
150+
141151
# 角色和权限操作
142152
def op_permission_with_role(self, client_id, permission, role, op="assign"):
143153
url = 'admin/realms/{realm-name}/clients/{cid}/authz/resource-server/permission/resource/{pid}'
144154
perm = self.get_permissions(client_id, permission)
145155
src_roles = self.get_permission_roles(client_id, permission)
146156
src_role_ids = [rid['id'] for rid in src_roles]
147157
npoid = self.get_policy_id(client_id, role)
148-
payload = {"id": perm['id'], "name": permission, "type": "resource", "logic": "POSITIVE", "decisionStrategy": "UNANIMOUS"}
158+
payload = {"id": perm['id'], "name": permission, "type": "resource",
159+
"logic": "POSITIVE", "decisionStrategy": "AFFIRMATIVE"}
149160
params_path = {'realm-name': self.realm_name,
150-
'pid': perm['id'], 'cid': self.get_client_id(client_id)}
161+
'pid': perm['id'], 'cid': self.get_client_id(client_id)}
151162
if op == "assign":
152163
if npoid in src_role_ids:
153164
return {}
@@ -160,23 +171,33 @@ def op_permission_with_role(self, client_id, permission, role, op="assign"):
160171
src_role_ids.remove(npoid)
161172
payload["resources"] = [self.get_resource_id(client_id, permission)]
162173
payload["policies"] = src_role_ids
163-
data_raw = self.raw_put(url.format(**params_path), data=json.dumps(payload))
174+
data_raw = self.raw_put(url.format(
175+
**params_path), data=json.dumps(payload))
164176
return raise_error_from_response(data_raw, KeycloakGetError)
165177

166-
# def get_role_permissions(self, rolename):
167-
# rid = self.get_role_id(rolename)
168-
# if not rid:
169-
# return self.errormsg("role {} not found".format(rolename))
170-
# url = "admin/realms/{realm-name}/groups/{rid}/role-mappings/clients/{cid}"
171-
# self.get_admin_cid()
172-
# params_path = {"realm-name": self.realm_name,
173-
# "rid": rid, "cid": self.cid}
174-
# data_raw = self.raw_get(url.format(**params_path))
175-
# return raise_error_from_response(data_raw, KeycloakGetError, expected_code=200)
178+
def get_role_permissions(self, client_id, rolename):
179+
client_settings = self.get_client_authz_settings(
180+
self.get_client_id(client_id)).json()
181+
policies = client_settings.get("policies")
182+
permissions = []
183+
role = None
184+
for rolep in policies:
185+
if rolep['type'] == 'role' and not role:
186+
if rolep['name'] == rolename:
187+
role = rolep
188+
else:
189+
if rolep['type'] == 'resource':
190+
rolepolicies = rolep['config'].get(
191+
'applyPolicies') if rolep['config'].get('applyPolicies') else []
192+
permissions.extend(
193+
[{'id': rolep['id'], 'name': rolep['name']}] if rolename in rolepolicies else [])
194+
role['permissions'] = permissions
195+
return role
176196

177197
def get_permission_roles(self, client_id, permission):
178198
url = 'admin/realms/{realm-name}/clients/{cid}/authz/resource-server/policy/{pid}/associatedPolicies'
179-
params_path = {'realm-name': self.realm_name, 'cid': self.get_client_id(client_id), 'pid': self.get_permissions(client_id, permission)['id']}
199+
params_path = {'realm-name': self.realm_name, 'cid': self.get_client_id(
200+
client_id), 'pid': self.get_permissions(client_id, permission)['id']}
180201
rawdata = self.raw_get(url.format(**params_path))
181202
return raise_error_from_response(rawdata, KeycloakGetError)
182203

0 commit comments

Comments
 (0)