You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2496 lines
89 KiB

  1. """Test the keycloak admin object."""
  2. import copy
  3. from typing import Tuple
  4. import pytest
  5. import keycloak
  6. from keycloak import KeycloakAdmin, KeycloakOpenID
  7. from keycloak.connection import ConnectionManager
  8. from keycloak.exceptions import (
  9. KeycloakAuthenticationError,
  10. KeycloakDeleteError,
  11. KeycloakGetError,
  12. KeycloakPostError,
  13. KeycloakPutError,
  14. )
  15. def test_keycloak_version():
  16. """Test version."""
  17. assert keycloak.__version__, keycloak.__version__
  18. def test_keycloak_admin_bad_init(env):
  19. """Test keycloak admin bad init.
  20. :param env: Environment fixture
  21. :type env: KeycloakTestEnv
  22. """
  23. with pytest.raises(TypeError) as err:
  24. KeycloakAdmin(
  25. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  26. username=env.KEYCLOAK_ADMIN,
  27. password=env.KEYCLOAK_ADMIN_PASSWORD,
  28. auto_refresh_token=1,
  29. )
  30. assert err.match("Expected a list of strings")
  31. with pytest.raises(TypeError) as err:
  32. KeycloakAdmin(
  33. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  34. username=env.KEYCLOAK_ADMIN,
  35. password=env.KEYCLOAK_ADMIN_PASSWORD,
  36. auto_refresh_token=["patch"],
  37. )
  38. assert err.match("Unexpected method in auto_refresh_token")
  39. def test_keycloak_admin_init(env):
  40. """Test keycloak admin init.
  41. :param env: Environment fixture
  42. :type env: KeycloakTestEnv
  43. """
  44. admin = KeycloakAdmin(
  45. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  46. username=env.KEYCLOAK_ADMIN,
  47. password=env.KEYCLOAK_ADMIN_PASSWORD,
  48. )
  49. assert admin.server_url == f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}", admin.server_url
  50. assert admin.realm_name == "master", admin.realm_name
  51. assert isinstance(admin.connection, ConnectionManager), type(admin.connection)
  52. assert admin.client_id == "admin-cli", admin.client_id
  53. assert admin.client_secret_key is None, admin.client_secret_key
  54. assert admin.verify, admin.verify
  55. assert admin.username == env.KEYCLOAK_ADMIN, admin.username
  56. assert admin.password == env.KEYCLOAK_ADMIN_PASSWORD, admin.password
  57. assert admin.totp is None, admin.totp
  58. assert admin.token is not None, admin.token
  59. assert admin.auto_refresh_token == list(), admin.auto_refresh_token
  60. assert admin.user_realm_name is None, admin.user_realm_name
  61. assert admin.custom_headers is None, admin.custom_headers
  62. assert admin.token
  63. admin = KeycloakAdmin(
  64. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  65. username=env.KEYCLOAK_ADMIN,
  66. password=env.KEYCLOAK_ADMIN_PASSWORD,
  67. realm_name=None,
  68. user_realm_name="master",
  69. )
  70. assert admin.token
  71. admin = KeycloakAdmin(
  72. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  73. username=env.KEYCLOAK_ADMIN,
  74. password=env.KEYCLOAK_ADMIN_PASSWORD,
  75. realm_name=None,
  76. user_realm_name=None,
  77. )
  78. assert admin.token
  79. admin.create_realm(payload={"realm": "authz", "enabled": True})
  80. admin.realm_name = "authz"
  81. admin.create_client(
  82. payload={
  83. "name": "authz-client",
  84. "clientId": "authz-client",
  85. "authorizationServicesEnabled": True,
  86. "serviceAccountsEnabled": True,
  87. "clientAuthenticatorType": "client-secret",
  88. "directAccessGrantsEnabled": False,
  89. "enabled": True,
  90. "implicitFlowEnabled": False,
  91. "publicClient": False,
  92. }
  93. )
  94. secret = admin.generate_client_secrets(client_id=admin.get_client_id("authz-client"))
  95. assert KeycloakAdmin(
  96. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  97. user_realm_name="authz",
  98. client_id="authz-client",
  99. client_secret_key=secret["value"],
  100. ).token
  101. admin.delete_realm(realm_name="authz")
  102. assert (
  103. KeycloakAdmin(
  104. server_url=f"http://{env.KEYCLOAK_HOST}:{env.KEYCLOAK_PORT}",
  105. username=None,
  106. password=None,
  107. client_secret_key=None,
  108. custom_headers={"custom": "header"},
  109. ).token
  110. is None
  111. )
  112. def test_realms(admin: KeycloakAdmin):
  113. """Test realms.
  114. :param admin: Keycloak Admin client
  115. :type admin: KeycloakAdmin
  116. """
  117. # Get realms
  118. realms = admin.get_realms()
  119. assert len(realms) == 1, realms
  120. assert "master" == realms[0]["realm"]
  121. # Create a test realm
  122. res = admin.create_realm(payload={"realm": "test"})
  123. assert res == b"", res
  124. # Create the same realm, should fail
  125. with pytest.raises(KeycloakPostError) as err:
  126. res = admin.create_realm(payload={"realm": "test"})
  127. assert err.match('409: b\'{"errorMessage":"Conflict detected. See logs for details"}\'')
  128. # Create the same realm, skip_exists true
  129. res = admin.create_realm(payload={"realm": "test"}, skip_exists=True)
  130. assert res == {"msg": "Already exists"}, res
  131. # Get a single realm
  132. res = admin.get_realm(realm_name="test")
  133. assert res["realm"] == "test"
  134. # Get non-existing realm
  135. with pytest.raises(KeycloakGetError) as err:
  136. admin.get_realm(realm_name="non-existent")
  137. assert err.match('404: b\'{"error":"Realm not found."}\'')
  138. # Update realm
  139. res = admin.update_realm(realm_name="test", payload={"accountTheme": "test"})
  140. assert res == dict(), res
  141. # Check that the update worked
  142. res = admin.get_realm(realm_name="test")
  143. assert res["realm"] == "test"
  144. assert res["accountTheme"] == "test"
  145. # Update wrong payload
  146. with pytest.raises(KeycloakPutError) as err:
  147. admin.update_realm(realm_name="test", payload={"wrong": "payload"})
  148. assert err.match('400: b\'{"error":"Unrecognized field')
  149. # Check that get realms returns both realms
  150. realms = admin.get_realms()
  151. realm_names = [x["realm"] for x in realms]
  152. assert len(realms) == 2, realms
  153. assert "master" in realm_names, realm_names
  154. assert "test" in realm_names, realm_names
  155. # Delete the realm
  156. res = admin.delete_realm(realm_name="test")
  157. assert res == dict(), res
  158. # Check that the realm does not exist anymore
  159. with pytest.raises(KeycloakGetError) as err:
  160. admin.get_realm(realm_name="test")
  161. assert err.match('404: b\'{"error":"Realm not found."}\'')
  162. # Delete non-existing realm
  163. with pytest.raises(KeycloakDeleteError) as err:
  164. admin.delete_realm(realm_name="non-existent")
  165. assert err.match('404: b\'{"error":"Realm not found."}\'')
  166. def test_import_export_realms(admin: KeycloakAdmin, realm: str):
  167. """Test import and export of realms.
  168. :param admin: Keycloak Admin client
  169. :type admin: KeycloakAdmin
  170. :param realm: Keycloak realm
  171. :type realm: str
  172. """
  173. admin.realm_name = realm
  174. realm_export = admin.export_realm(export_clients=True, export_groups_and_role=True)
  175. assert realm_export != dict(), realm_export
  176. admin.delete_realm(realm_name=realm)
  177. admin.realm_name = "master"
  178. res = admin.import_realm(payload=realm_export)
  179. assert res == b"", res
  180. # Test bad import
  181. with pytest.raises(KeycloakPostError) as err:
  182. admin.import_realm(payload=dict())
  183. assert err.match('500: b\'{"error":"unknown_error"}\'')
  184. def test_users(admin: KeycloakAdmin, realm: str):
  185. """Test users.
  186. :param admin: Keycloak Admin client
  187. :type admin: KeycloakAdmin
  188. :param realm: Keycloak realm
  189. :type realm: str
  190. """
  191. admin.realm_name = realm
  192. # Check no users present
  193. users = admin.get_users()
  194. assert users == list(), users
  195. # Test create user
  196. user_id = admin.create_user(payload={"username": "test", "email": "test@test.test"})
  197. assert user_id is not None, user_id
  198. # Test create the same user
  199. with pytest.raises(KeycloakPostError) as err:
  200. admin.create_user(payload={"username": "test", "email": "test@test.test"})
  201. assert err.match('409: b\'{"errorMessage":"User exists with same username"}\'')
  202. # Test create the same user, exists_ok true
  203. user_id_2 = admin.create_user(
  204. payload={"username": "test", "email": "test@test.test"}, exist_ok=True
  205. )
  206. assert user_id == user_id_2
  207. # Test get user
  208. user = admin.get_user(user_id=user_id)
  209. assert user["username"] == "test", user["username"]
  210. assert user["email"] == "test@test.test", user["email"]
  211. # Test update user
  212. res = admin.update_user(user_id=user_id, payload={"firstName": "Test"})
  213. assert res == dict(), res
  214. user = admin.get_user(user_id=user_id)
  215. assert user["firstName"] == "Test"
  216. # Test update user fail
  217. with pytest.raises(KeycloakPutError) as err:
  218. admin.update_user(user_id=user_id, payload={"wrong": "payload"})
  219. assert err.match('400: b\'{"error":"Unrecognized field')
  220. # Test get users again
  221. users = admin.get_users()
  222. usernames = [x["username"] for x in users]
  223. assert "test" in usernames
  224. # Test users counts
  225. count = admin.users_count()
  226. assert count == 1, count
  227. # Test users count with query
  228. count = admin.users_count(query={"username": "notpresent"})
  229. assert count == 0
  230. # Test user groups
  231. groups = admin.get_user_groups(user_id=user["id"])
  232. assert len(groups) == 0
  233. # Test user groups bad id
  234. with pytest.raises(KeycloakGetError) as err:
  235. admin.get_user_groups(user_id="does-not-exist")
  236. assert err.match('404: b\'{"error":"User not found"}\'')
  237. # Test logout
  238. res = admin.user_logout(user_id=user["id"])
  239. assert res == dict(), res
  240. # Test logout fail
  241. with pytest.raises(KeycloakPostError) as err:
  242. admin.user_logout(user_id="non-existent-id")
  243. assert err.match('404: b\'{"error":"User not found"}\'')
  244. # Test consents
  245. res = admin.user_consents(user_id=user["id"])
  246. assert len(res) == 0, res
  247. # Test consents fail
  248. with pytest.raises(KeycloakGetError) as err:
  249. admin.user_consents(user_id="non-existent-id")
  250. assert err.match('404: b\'{"error":"User not found"}\'')
  251. # Test delete user
  252. res = admin.delete_user(user_id=user_id)
  253. assert res == dict(), res
  254. with pytest.raises(KeycloakGetError) as err:
  255. admin.get_user(user_id=user_id)
  256. err.match('404: b\'{"error":"User not found"}\'')
  257. # Test delete fail
  258. with pytest.raises(KeycloakDeleteError) as err:
  259. admin.delete_user(user_id="non-existent-id")
  260. assert err.match('404: b\'{"error":"User not found"}\'')
  261. def test_users_pagination(admin: KeycloakAdmin, realm: str):
  262. """Test user pagination.
  263. :param admin: Keycloak Admin client
  264. :type admin: KeycloakAdmin
  265. :param realm: Keycloak realm
  266. :type realm: str
  267. """
  268. admin.realm_name = realm
  269. for ind in range(admin.PAGE_SIZE + 50):
  270. username = f"user_{ind}"
  271. admin.create_user(payload={"username": username, "email": f"{username}@test.test"})
  272. users = admin.get_users()
  273. assert len(users) == admin.PAGE_SIZE + 50, len(users)
  274. users = admin.get_users(query={"first": 100})
  275. assert len(users) == 50, len(users)
  276. users = admin.get_users(query={"max": 20})
  277. assert len(users) == 20, len(users)
  278. def test_idps(admin: KeycloakAdmin, realm: str):
  279. """Test IDPs.
  280. :param admin: Keycloak Admin client
  281. :type admin: KeycloakAdmin
  282. :param realm: Keycloak realm
  283. :type realm: str
  284. """
  285. admin.realm_name = realm
  286. # Create IDP
  287. res = admin.create_idp(
  288. payload=dict(
  289. providerId="github", alias="github", config=dict(clientId="test", clientSecret="test")
  290. )
  291. )
  292. assert res == b"", res
  293. # Test create idp fail
  294. with pytest.raises(KeycloakPostError) as err:
  295. admin.create_idp(payload={"providerId": "does-not-exist", "alias": "something"})
  296. assert err.match("Invalid identity provider id"), err
  297. # Test listing
  298. idps = admin.get_idps()
  299. assert len(idps) == 1
  300. assert "github" == idps[0]["alias"]
  301. # Test IdP update
  302. res = admin.update_idp(idp_alias="github", payload=idps[0])
  303. assert res == {}, res
  304. # Test adding a mapper
  305. res = admin.add_mapper_to_idp(
  306. idp_alias="github",
  307. payload={
  308. "identityProviderAlias": "github",
  309. "identityProviderMapper": "github-user-attribute-mapper",
  310. "name": "test",
  311. },
  312. )
  313. assert res == b"", res
  314. # Test mapper fail
  315. with pytest.raises(KeycloakPostError) as err:
  316. admin.add_mapper_to_idp(idp_alias="does-no-texist", payload=dict())
  317. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  318. # Test IdP mappers listing
  319. idp_mappers = admin.get_idp_mappers(idp_alias="github")
  320. assert len(idp_mappers) == 1
  321. # Test IdP mapper update
  322. res = admin.update_mapper_in_idp(
  323. idp_alias="github",
  324. mapper_id=idp_mappers[0]["id"],
  325. # For an obscure reason, keycloak expect all fields
  326. payload={
  327. "id": idp_mappers[0]["id"],
  328. "identityProviderAlias": "github-alias",
  329. "identityProviderMapper": "github-user-attribute-mapper",
  330. "name": "test",
  331. "config": idp_mappers[0]["config"],
  332. },
  333. )
  334. assert res == dict(), res
  335. # Test delete
  336. res = admin.delete_idp(idp_alias="github")
  337. assert res == dict(), res
  338. # Test delete fail
  339. with pytest.raises(KeycloakDeleteError) as err:
  340. admin.delete_idp(idp_alias="does-not-exist")
  341. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  342. def test_user_credentials(admin: KeycloakAdmin, user: str):
  343. """Test user credentials.
  344. :param admin: Keycloak Admin client
  345. :type admin: KeycloakAdmin
  346. :param user: Keycloak user
  347. :type user: str
  348. """
  349. res = admin.set_user_password(user_id=user, password="booya", temporary=True)
  350. assert res == dict(), res
  351. # Test user password set fail
  352. with pytest.raises(KeycloakPutError) as err:
  353. admin.set_user_password(user_id="does-not-exist", password="")
  354. assert err.match('404: b\'{"error":"User not found"}\'')
  355. credentials = admin.get_credentials(user_id=user)
  356. assert len(credentials) == 1
  357. assert credentials[0]["type"] == "password", credentials
  358. # Test get credentials fail
  359. with pytest.raises(KeycloakGetError) as err:
  360. admin.get_credentials(user_id="does-not-exist")
  361. assert err.match('404: b\'{"error":"User not found"}\'')
  362. res = admin.delete_credential(user_id=user, credential_id=credentials[0]["id"])
  363. assert res == dict(), res
  364. # Test delete fail
  365. with pytest.raises(KeycloakDeleteError) as err:
  366. admin.delete_credential(user_id=user, credential_id="does-not-exist")
  367. assert err.match('404: b\'{"error":"Credential not found"}\'')
  368. def test_social_logins(admin: KeycloakAdmin, user: str):
  369. """Test social logins.
  370. :param admin: Keycloak Admin client
  371. :type admin: KeycloakAdmin
  372. :param user: Keycloak user
  373. :type user: str
  374. """
  375. res = admin.add_user_social_login(
  376. user_id=user, provider_id="gitlab", provider_userid="test", provider_username="test"
  377. )
  378. assert res == dict(), res
  379. admin.add_user_social_login(
  380. user_id=user, provider_id="github", provider_userid="test", provider_username="test"
  381. )
  382. assert res == dict(), res
  383. # Test add social login fail
  384. with pytest.raises(KeycloakPostError) as err:
  385. admin.add_user_social_login(
  386. user_id="does-not-exist",
  387. provider_id="does-not-exist",
  388. provider_userid="test",
  389. provider_username="test",
  390. )
  391. assert err.match('404: b\'{"error":"User not found"}\'')
  392. res = admin.get_user_social_logins(user_id=user)
  393. assert res == list(), res
  394. # Test get social logins fail
  395. with pytest.raises(KeycloakGetError) as err:
  396. admin.get_user_social_logins(user_id="does-not-exist")
  397. assert err.match('404: b\'{"error":"User not found"}\'')
  398. res = admin.delete_user_social_login(user_id=user, provider_id="gitlab")
  399. assert res == {}, res
  400. res = admin.delete_user_social_login(user_id=user, provider_id="github")
  401. assert res == {}, res
  402. with pytest.raises(KeycloakDeleteError) as err:
  403. admin.delete_user_social_login(user_id=user, provider_id="instagram")
  404. assert err.match('404: b\'{"error":"Link not found"}\''), err
  405. def test_server_info(admin: KeycloakAdmin):
  406. """Test server info.
  407. :param admin: Keycloak Admin client
  408. :type admin: KeycloakAdmin
  409. """
  410. info = admin.get_server_info()
  411. assert set(info.keys()).issubset(
  412. {
  413. "systemInfo",
  414. "memoryInfo",
  415. "profileInfo",
  416. "themes",
  417. "socialProviders",
  418. "identityProviders",
  419. "providers",
  420. "protocolMapperTypes",
  421. "builtinProtocolMappers",
  422. "clientInstallations",
  423. "componentTypes",
  424. "passwordPolicies",
  425. "enums",
  426. "cryptoInfo",
  427. }
  428. ), info.keys()
  429. def test_groups(admin: KeycloakAdmin, user: str):
  430. """Test groups.
  431. :param admin: Keycloak Admin client
  432. :type admin: KeycloakAdmin
  433. :param user: Keycloak user
  434. :type user: str
  435. """
  436. # Test get groups
  437. groups = admin.get_groups()
  438. assert len(groups) == 0
  439. # Test create group
  440. group_id = admin.create_group(payload={"name": "main-group"})
  441. assert group_id is not None, group_id
  442. # Test create subgroups
  443. subgroup_id_1 = admin.create_group(payload={"name": "subgroup-1"}, parent=group_id)
  444. subgroup_id_2 = admin.create_group(payload={"name": "subgroup-2"}, parent=group_id)
  445. # Test create group fail
  446. with pytest.raises(KeycloakPostError) as err:
  447. admin.create_group(payload={"name": "subgroup-1"}, parent=group_id)
  448. assert err.match('409: b\'{"error":"unknown_error"}\''), err
  449. # Test skip exists OK
  450. subgroup_id_1_eq = admin.create_group(
  451. payload={"name": "subgroup-1"}, parent=group_id, skip_exists=True
  452. )
  453. assert subgroup_id_1_eq is None
  454. # Test get groups again
  455. groups = admin.get_groups()
  456. assert len(groups) == 1, groups
  457. assert len(groups[0]["subGroups"]) == 2, groups["subGroups"]
  458. assert groups[0]["id"] == group_id
  459. assert {x["id"] for x in groups[0]["subGroups"]} == {subgroup_id_1, subgroup_id_2}
  460. # Test get groups query
  461. groups = admin.get_groups(query={"max": 10})
  462. assert len(groups) == 1, groups
  463. assert len(groups[0]["subGroups"]) == 2, groups["subGroups"]
  464. assert groups[0]["id"] == group_id
  465. assert {x["id"] for x in groups[0]["subGroups"]} == {subgroup_id_1, subgroup_id_2}
  466. # Test get group
  467. res = admin.get_group(group_id=subgroup_id_1)
  468. assert res["id"] == subgroup_id_1, res
  469. assert res["name"] == "subgroup-1"
  470. assert res["path"] == "/main-group/subgroup-1"
  471. # Test get group fail
  472. with pytest.raises(KeycloakGetError) as err:
  473. admin.get_group(group_id="does-not-exist")
  474. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  475. # Create 1 more subgroup
  476. subsubgroup_id_1 = admin.create_group(payload={"name": "subsubgroup-1"}, parent=subgroup_id_2)
  477. main_group = admin.get_group(group_id=group_id)
  478. # Test nested searches
  479. res = admin.get_subgroups(group=main_group, path="/main-group/subgroup-2/subsubgroup-1")
  480. assert res is not None, res
  481. assert res["id"] == subsubgroup_id_1
  482. # Test empty search
  483. res = admin.get_subgroups(group=main_group, path="/none")
  484. assert res is None, res
  485. # Test get group by path
  486. res = admin.get_group_by_path(path="/main-group/subgroup-1")
  487. assert res is None, res
  488. res = admin.get_group_by_path(path="/main-group/subgroup-1", search_in_subgroups=True)
  489. assert res is not None, res
  490. assert res["id"] == subgroup_id_1, res
  491. res = admin.get_group_by_path(
  492. path="/main-group/subgroup-2/subsubgroup-1/test", search_in_subgroups=True
  493. )
  494. assert res is None, res
  495. res = admin.get_group_by_path(
  496. path="/main-group/subgroup-2/subsubgroup-1", search_in_subgroups=True
  497. )
  498. assert res is not None, res
  499. assert res["id"] == subsubgroup_id_1
  500. res = admin.get_group_by_path(path="/main-group")
  501. assert res is not None, res
  502. assert res["id"] == group_id, res
  503. # Test group members
  504. res = admin.get_group_members(group_id=subgroup_id_2)
  505. assert len(res) == 0, res
  506. # Test fail group members
  507. with pytest.raises(KeycloakGetError) as err:
  508. admin.get_group_members(group_id="does-not-exist")
  509. assert err.match('404: b\'{"error":"Could not find group by id"}\'')
  510. res = admin.group_user_add(user_id=user, group_id=subgroup_id_2)
  511. assert res == dict(), res
  512. res = admin.get_group_members(group_id=subgroup_id_2)
  513. assert len(res) == 1, res
  514. assert res[0]["id"] == user
  515. # Test get group members query
  516. res = admin.get_group_members(group_id=subgroup_id_2, query={"max": 10})
  517. assert len(res) == 1, res
  518. assert res[0]["id"] == user
  519. with pytest.raises(KeycloakDeleteError) as err:
  520. admin.group_user_remove(user_id="does-not-exist", group_id=subgroup_id_2)
  521. assert err.match('404: b\'{"error":"User not found"}\''), err
  522. res = admin.group_user_remove(user_id=user, group_id=subgroup_id_2)
  523. assert res == dict(), res
  524. # Test set permissions
  525. res = admin.group_set_permissions(group_id=subgroup_id_2, enabled=True)
  526. assert res["enabled"], res
  527. res = admin.group_set_permissions(group_id=subgroup_id_2, enabled=False)
  528. assert not res["enabled"], res
  529. with pytest.raises(KeycloakPutError) as err:
  530. admin.group_set_permissions(group_id=subgroup_id_2, enabled="blah")
  531. assert err.match('500: b\'{"error":"unknown_error"}\''), err
  532. # Test update group
  533. res = admin.update_group(group_id=subgroup_id_2, payload={"name": "new-subgroup-2"})
  534. assert res == dict(), res
  535. assert admin.get_group(group_id=subgroup_id_2)["name"] == "new-subgroup-2"
  536. # test update fail
  537. with pytest.raises(KeycloakPutError) as err:
  538. admin.update_group(group_id="does-not-exist", payload=dict())
  539. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  540. # Test delete
  541. res = admin.delete_group(group_id=group_id)
  542. assert res == dict(), res
  543. assert len(admin.get_groups()) == 0
  544. # Test delete fail
  545. with pytest.raises(KeycloakDeleteError) as err:
  546. admin.delete_group(group_id="does-not-exist")
  547. assert err.match('404: b\'{"error":"Could not find group by id"}\''), err
  548. def test_clients(admin: KeycloakAdmin, realm: str):
  549. """Test clients.
  550. :param admin: Keycloak Admin client
  551. :type admin: KeycloakAdmin
  552. :param realm: Keycloak realm
  553. :type realm: str
  554. """
  555. admin.realm_name = realm
  556. # Test get clients
  557. clients = admin.get_clients()
  558. assert len(clients) == 6, clients
  559. assert {x["name"] for x in clients} == set(
  560. [
  561. "${client_admin-cli}",
  562. "${client_security-admin-console}",
  563. "${client_account-console}",
  564. "${client_broker}",
  565. "${client_account}",
  566. "${client_realm-management}",
  567. ]
  568. ), clients
  569. # Test create client
  570. client_id = admin.create_client(payload={"name": "test-client", "clientId": "test-client"})
  571. assert client_id, client_id
  572. with pytest.raises(KeycloakPostError) as err:
  573. admin.create_client(payload={"name": "test-client", "clientId": "test-client"})
  574. assert err.match('409: b\'{"errorMessage":"Client test-client already exists"}\''), err
  575. client_id_2 = admin.create_client(
  576. payload={"name": "test-client", "clientId": "test-client"}, skip_exists=True
  577. )
  578. assert client_id == client_id_2, client_id_2
  579. # Test get client
  580. res = admin.get_client(client_id=client_id)
  581. assert res["clientId"] == "test-client", res
  582. assert res["name"] == "test-client", res
  583. assert res["id"] == client_id, res
  584. with pytest.raises(KeycloakGetError) as err:
  585. admin.get_client(client_id="does-not-exist")
  586. assert err.match('404: b\'{"error":"Could not find client"}\'')
  587. assert len(admin.get_clients()) == 7
  588. # Test get client id
  589. assert admin.get_client_id(client_id="test-client") == client_id
  590. assert admin.get_client_id(client_id="does-not-exist") is None
  591. # Test update client
  592. res = admin.update_client(client_id=client_id, payload={"name": "test-client-change"})
  593. assert res == dict(), res
  594. with pytest.raises(KeycloakPutError) as err:
  595. admin.update_client(client_id="does-not-exist", payload={"name": "test-client-change"})
  596. assert err.match('404: b\'{"error":"Could not find client"}\'')
  597. # Test client mappers
  598. res = admin.get_mappers_from_client(client_id=client_id)
  599. assert len(res) == 0
  600. with pytest.raises(KeycloakPostError) as err:
  601. admin.add_mapper_to_client(client_id="does-not-exist", payload=dict())
  602. assert err.match('404: b\'{"error":"Could not find client"}\'')
  603. res = admin.add_mapper_to_client(
  604. client_id=client_id,
  605. payload={
  606. "name": "test-mapper",
  607. "protocol": "openid-connect",
  608. "protocolMapper": "oidc-usermodel-attribute-mapper",
  609. },
  610. )
  611. assert res == b""
  612. assert len(admin.get_mappers_from_client(client_id=client_id)) == 1
  613. mapper = admin.get_mappers_from_client(client_id=client_id)[0]
  614. with pytest.raises(KeycloakPutError) as err:
  615. admin.update_client_mapper(client_id=client_id, mapper_id="does-not-exist", payload=dict())
  616. assert err.match('404: b\'{"error":"Model not found"}\'')
  617. mapper["config"]["user.attribute"] = "test"
  618. res = admin.update_client_mapper(client_id=client_id, mapper_id=mapper["id"], payload=mapper)
  619. assert res == dict()
  620. res = admin.remove_client_mapper(client_id=client_id, client_mapper_id=mapper["id"])
  621. assert res == dict()
  622. with pytest.raises(KeycloakDeleteError) as err:
  623. admin.remove_client_mapper(client_id=client_id, client_mapper_id=mapper["id"])
  624. assert err.match('404: b\'{"error":"Model not found"}\'')
  625. # Test client sessions
  626. with pytest.raises(KeycloakGetError) as err:
  627. admin.get_client_all_sessions(client_id="does-not-exist")
  628. assert err.match('404: b\'{"error":"Could not find client"}\'')
  629. assert admin.get_client_all_sessions(client_id=client_id) == list()
  630. assert admin.get_client_sessions_stats() == list()
  631. # Test authz
  632. auth_client_id = admin.create_client(
  633. payload={
  634. "name": "authz-client",
  635. "clientId": "authz-client",
  636. "authorizationServicesEnabled": True,
  637. "serviceAccountsEnabled": True,
  638. }
  639. )
  640. res = admin.get_client_authz_settings(client_id=auth_client_id)
  641. assert res["allowRemoteResourceManagement"]
  642. assert res["decisionStrategy"] == "UNANIMOUS"
  643. assert len(res["policies"]) >= 0
  644. with pytest.raises(KeycloakGetError) as err:
  645. admin.get_client_authz_settings(client_id=client_id)
  646. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  647. # Authz resources
  648. res = admin.get_client_authz_resources(client_id=auth_client_id)
  649. assert len(res) == 1
  650. assert res[0]["name"] == "Default Resource"
  651. with pytest.raises(KeycloakGetError) as err:
  652. admin.get_client_authz_resources(client_id=client_id)
  653. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  654. res = admin.create_client_authz_resource(
  655. client_id=auth_client_id, payload={"name": "test-resource"}
  656. )
  657. assert res["name"] == "test-resource", res
  658. test_resource_id = res["_id"]
  659. with pytest.raises(KeycloakPostError) as err:
  660. admin.create_client_authz_resource(
  661. client_id=auth_client_id, payload={"name": "test-resource"}
  662. )
  663. assert err.match('409: b\'{"error":"invalid_request"')
  664. assert admin.create_client_authz_resource(
  665. client_id=auth_client_id, payload={"name": "test-resource"}, skip_exists=True
  666. ) == {"msg": "Already exists"}
  667. res = admin.get_client_authz_resources(client_id=auth_client_id)
  668. assert len(res) == 2
  669. assert {x["name"] for x in res} == {"Default Resource", "test-resource"}
  670. # Authz policies
  671. res = admin.get_client_authz_policies(client_id=auth_client_id)
  672. assert len(res) == 1, res
  673. assert res[0]["name"] == "Default Policy"
  674. with pytest.raises(KeycloakGetError) as err:
  675. admin.get_client_authz_policies(client_id="does-not-exist")
  676. assert err.match('404: b\'{"error":"Could not find client"}\'')
  677. role_id = admin.get_realm_role(role_name="offline_access")["id"]
  678. res = admin.create_client_authz_role_based_policy(
  679. client_id=auth_client_id,
  680. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  681. )
  682. assert res["name"] == "test-authz-rb-policy", res
  683. with pytest.raises(KeycloakPostError) as err:
  684. admin.create_client_authz_role_based_policy(
  685. client_id=auth_client_id,
  686. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  687. )
  688. assert err.match('409: b\'{"error":"Policy with name')
  689. assert admin.create_client_authz_role_based_policy(
  690. client_id=auth_client_id,
  691. payload={"name": "test-authz-rb-policy", "roles": [{"id": role_id}]},
  692. skip_exists=True,
  693. ) == {"msg": "Already exists"}
  694. assert len(admin.get_client_authz_policies(client_id=auth_client_id)) == 2
  695. # Test authz permissions
  696. res = admin.get_client_authz_permissions(client_id=auth_client_id)
  697. assert len(res) == 1, res
  698. assert res[0]["name"] == "Default Permission"
  699. with pytest.raises(KeycloakGetError) as err:
  700. admin.get_client_authz_permissions(client_id="does-not-exist")
  701. assert err.match('404: b\'{"error":"Could not find client"}\'')
  702. res = admin.create_client_authz_resource_based_permission(
  703. client_id=auth_client_id,
  704. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  705. )
  706. assert res, res
  707. assert res["name"] == "test-permission-rb"
  708. assert res["resources"] == [test_resource_id]
  709. with pytest.raises(KeycloakPostError) as err:
  710. admin.create_client_authz_resource_based_permission(
  711. client_id=auth_client_id,
  712. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  713. )
  714. assert err.match('409: b\'{"error":"Policy with name')
  715. assert admin.create_client_authz_resource_based_permission(
  716. client_id=auth_client_id,
  717. payload={"name": "test-permission-rb", "resources": [test_resource_id]},
  718. skip_exists=True,
  719. ) == {"msg": "Already exists"}
  720. assert len(admin.get_client_authz_permissions(client_id=auth_client_id)) == 2
  721. # Test authz scopes
  722. res = admin.get_client_authz_scopes(client_id=auth_client_id)
  723. assert len(res) == 0, res
  724. with pytest.raises(KeycloakGetError) as err:
  725. admin.get_client_authz_scopes(client_id=client_id)
  726. assert err.match('404: b\'{"error":"HTTP 404 Not Found"}\'')
  727. res = admin.create_client_authz_scopes(
  728. client_id=auth_client_id, payload={"name": "test-authz-scope"}
  729. )
  730. assert res["name"] == "test-authz-scope", res
  731. with pytest.raises(KeycloakPostError) as err:
  732. admin.create_client_authz_scopes(
  733. client_id="invalid_client_id", payload={"name": "test-authz-scope"}
  734. )
  735. assert err.match('404: b\'{"error":"Could not find client"')
  736. assert admin.create_client_authz_scopes(
  737. client_id=auth_client_id, payload={"name": "test-authz-scope"}
  738. )
  739. res = admin.get_client_authz_scopes(client_id=auth_client_id)
  740. assert len(res) == 1
  741. assert {x["name"] for x in res} == {"test-authz-scope"}
  742. # Test service account user
  743. res = admin.get_client_service_account_user(client_id=auth_client_id)
  744. assert res["username"] == "service-account-authz-client", res
  745. with pytest.raises(KeycloakGetError) as err:
  746. admin.get_client_service_account_user(client_id=client_id)
  747. assert err.match('400: b\'{"error":"unknown_error"}\'')
  748. # Test delete client
  749. res = admin.delete_client(client_id=auth_client_id)
  750. assert res == dict(), res
  751. with pytest.raises(KeycloakDeleteError) as err:
  752. admin.delete_client(client_id=auth_client_id)
  753. assert err.match('404: b\'{"error":"Could not find client"}\'')
  754. # Test client credentials
  755. admin.create_client(
  756. payload={
  757. "name": "test-confidential",
  758. "enabled": True,
  759. "protocol": "openid-connect",
  760. "publicClient": False,
  761. "redirectUris": ["http://localhost/*"],
  762. "webOrigins": ["+"],
  763. "clientId": "test-confidential",
  764. "secret": "test-secret",
  765. "clientAuthenticatorType": "client-secret",
  766. }
  767. )
  768. with pytest.raises(KeycloakGetError) as err:
  769. admin.get_client_secrets(client_id="does-not-exist")
  770. assert err.match('404: b\'{"error":"Could not find client"}\'')
  771. secrets = admin.get_client_secrets(
  772. client_id=admin.get_client_id(client_id="test-confidential")
  773. )
  774. assert secrets == {"type": "secret", "value": "test-secret"}
  775. with pytest.raises(KeycloakPostError) as err:
  776. admin.generate_client_secrets(client_id="does-not-exist")
  777. assert err.match('404: b\'{"error":"Could not find client"}\'')
  778. res = admin.generate_client_secrets(
  779. client_id=admin.get_client_id(client_id="test-confidential")
  780. )
  781. assert res
  782. assert (
  783. admin.get_client_secrets(client_id=admin.get_client_id(client_id="test-confidential"))
  784. == res
  785. )
  786. def test_realm_roles(admin: KeycloakAdmin, realm: str):
  787. """Test realm roles.
  788. :param admin: Keycloak Admin client
  789. :type admin: KeycloakAdmin
  790. :param realm: Keycloak realm
  791. :type realm: str
  792. """
  793. admin.realm_name = realm
  794. # Test get realm roles
  795. roles = admin.get_realm_roles()
  796. assert len(roles) == 3, roles
  797. role_names = [x["name"] for x in roles]
  798. assert "uma_authorization" in role_names, role_names
  799. assert "offline_access" in role_names, role_names
  800. # Test empty members
  801. with pytest.raises(KeycloakGetError) as err:
  802. admin.get_realm_role_members(role_name="does-not-exist")
  803. assert err.match('404: b\'{"error":"Could not find role"}\'')
  804. members = admin.get_realm_role_members(role_name="offline_access")
  805. assert members == list(), members
  806. # Test create realm role
  807. role_id = admin.create_realm_role(payload={"name": "test-realm-role"}, skip_exists=True)
  808. assert role_id, role_id
  809. with pytest.raises(KeycloakPostError) as err:
  810. admin.create_realm_role(payload={"name": "test-realm-role"})
  811. assert err.match('409: b\'{"errorMessage":"Role with name test-realm-role already exists"}\'')
  812. role_id_2 = admin.create_realm_role(payload={"name": "test-realm-role"}, skip_exists=True)
  813. assert role_id == role_id_2
  814. # Test update realm role
  815. res = admin.update_realm_role(
  816. role_name="test-realm-role", payload={"name": "test-realm-role-update"}
  817. )
  818. assert res == dict(), res
  819. with pytest.raises(KeycloakPutError) as err:
  820. admin.update_realm_role(
  821. role_name="test-realm-role", payload={"name": "test-realm-role-update"}
  822. )
  823. assert err.match('404: b\'{"error":"Could not find role"}\''), err
  824. # Test realm role user assignment
  825. user_id = admin.create_user(payload={"username": "role-testing", "email": "test@test.test"})
  826. with pytest.raises(KeycloakPostError) as err:
  827. admin.assign_realm_roles(user_id=user_id, roles=["bad"])
  828. assert err.match('500: b\'{"error":"unknown_error"}\'')
  829. res = admin.assign_realm_roles(
  830. user_id=user_id,
  831. roles=[
  832. admin.get_realm_role(role_name="offline_access"),
  833. admin.get_realm_role(role_name="test-realm-role-update"),
  834. ],
  835. )
  836. assert res == dict(), res
  837. assert admin.get_user(user_id=user_id)["username"] in [
  838. x["username"] for x in admin.get_realm_role_members(role_name="offline_access")
  839. ]
  840. assert admin.get_user(user_id=user_id)["username"] in [
  841. x["username"] for x in admin.get_realm_role_members(role_name="test-realm-role-update")
  842. ]
  843. roles = admin.get_realm_roles_of_user(user_id=user_id)
  844. assert len(roles) == 3
  845. assert "offline_access" in [x["name"] for x in roles]
  846. assert "test-realm-role-update" in [x["name"] for x in roles]
  847. with pytest.raises(KeycloakDeleteError) as err:
  848. admin.delete_realm_roles_of_user(user_id=user_id, roles=["bad"])
  849. assert err.match('500: b\'{"error":"unknown_error"}\'')
  850. res = admin.delete_realm_roles_of_user(
  851. user_id=user_id, roles=[admin.get_realm_role(role_name="offline_access")]
  852. )
  853. assert res == dict(), res
  854. assert admin.get_realm_role_members(role_name="offline_access") == list()
  855. roles = admin.get_realm_roles_of_user(user_id=user_id)
  856. assert len(roles) == 2
  857. assert "offline_access" not in [x["name"] for x in roles]
  858. assert "test-realm-role-update" in [x["name"] for x in roles]
  859. roles = admin.get_available_realm_roles_of_user(user_id=user_id)
  860. assert len(roles) == 2
  861. assert "offline_access" in [x["name"] for x in roles]
  862. assert "uma_authorization" in [x["name"] for x in roles]
  863. # Test realm role group assignment
  864. group_id = admin.create_group(payload={"name": "test-group"})
  865. with pytest.raises(KeycloakPostError) as err:
  866. admin.assign_group_realm_roles(group_id=group_id, roles=["bad"])
  867. assert err.match('500: b\'{"error":"unknown_error"}\'')
  868. res = admin.assign_group_realm_roles(
  869. group_id=group_id,
  870. roles=[
  871. admin.get_realm_role(role_name="offline_access"),
  872. admin.get_realm_role(role_name="test-realm-role-update"),
  873. ],
  874. )
  875. assert res == dict(), res
  876. roles = admin.get_group_realm_roles(group_id=group_id)
  877. assert len(roles) == 2
  878. assert "offline_access" in [x["name"] for x in roles]
  879. assert "test-realm-role-update" in [x["name"] for x in roles]
  880. with pytest.raises(KeycloakDeleteError) as err:
  881. admin.delete_group_realm_roles(group_id=group_id, roles=["bad"])
  882. assert err.match('500: b\'{"error":"unknown_error"}\'')
  883. res = admin.delete_group_realm_roles(
  884. group_id=group_id, roles=[admin.get_realm_role(role_name="offline_access")]
  885. )
  886. assert res == dict(), res
  887. roles = admin.get_group_realm_roles(group_id=group_id)
  888. assert len(roles) == 1
  889. assert "test-realm-role-update" in [x["name"] for x in roles]
  890. # Test composite realm roles
  891. composite_role = admin.create_realm_role(payload={"name": "test-composite-role"})
  892. with pytest.raises(KeycloakPostError) as err:
  893. admin.add_composite_realm_roles_to_role(role_name=composite_role, roles=["bad"])
  894. assert err.match('500: b\'{"error":"unknown_error"}\'')
  895. res = admin.add_composite_realm_roles_to_role(
  896. role_name=composite_role, roles=[admin.get_realm_role(role_name="test-realm-role-update")]
  897. )
  898. assert res == dict(), res
  899. res = admin.get_composite_realm_roles_of_role(role_name=composite_role)
  900. assert len(res) == 1
  901. assert "test-realm-role-update" in res[0]["name"]
  902. with pytest.raises(KeycloakGetError) as err:
  903. admin.get_composite_realm_roles_of_role(role_name="bad")
  904. assert err.match('404: b\'{"error":"Could not find role"}\'')
  905. res = admin.get_composite_realm_roles_of_user(user_id=user_id)
  906. assert len(res) == 4
  907. assert "offline_access" in {x["name"] for x in res}
  908. assert "test-realm-role-update" in {x["name"] for x in res}
  909. assert "uma_authorization" in {x["name"] for x in res}
  910. with pytest.raises(KeycloakGetError) as err:
  911. admin.get_composite_realm_roles_of_user(user_id="bad")
  912. assert err.match('404: b\'{"error":"User not found"}\'')
  913. with pytest.raises(KeycloakDeleteError) as err:
  914. admin.remove_composite_realm_roles_to_role(role_name=composite_role, roles=["bad"])
  915. assert err.match('500: b\'{"error":"unknown_error"}\'')
  916. res = admin.remove_composite_realm_roles_to_role(
  917. role_name=composite_role, roles=[admin.get_realm_role(role_name="test-realm-role-update")]
  918. )
  919. assert res == dict(), res
  920. res = admin.get_composite_realm_roles_of_role(role_name=composite_role)
  921. assert len(res) == 0
  922. # Test delete realm role
  923. res = admin.delete_realm_role(role_name=composite_role)
  924. assert res == dict(), res
  925. with pytest.raises(KeycloakDeleteError) as err:
  926. admin.delete_realm_role(role_name=composite_role)
  927. assert err.match('404: b\'{"error":"Could not find role"}\'')
  928. @pytest.mark.parametrize(
  929. "testcase, arg_brief_repr, includes_attributes",
  930. [
  931. ("brief True", {"brief_representation": True}, False),
  932. ("brief False", {"brief_representation": False}, True),
  933. ("default", {}, False),
  934. ],
  935. )
  936. def test_role_attributes(
  937. admin: KeycloakAdmin,
  938. realm: str,
  939. client: str,
  940. arg_brief_repr: dict,
  941. includes_attributes: bool,
  942. testcase: str,
  943. ):
  944. """Test getting role attributes for bulk calls.
  945. :param admin: Keycloak admin
  946. :type admin: KeycloakAdmin
  947. :param realm: Keycloak realm
  948. :type realm: str
  949. :param client: Keycloak client
  950. :type client: str
  951. :param arg_brief_repr: Brief representation
  952. :type arg_brief_repr: dict
  953. :param includes_attributes: Indicator whether to include attributes
  954. :type includes_attributes: bool
  955. :param testcase: Test case
  956. :type testcase: str
  957. """
  958. # setup
  959. attribute_role = "test-realm-role-w-attr"
  960. test_attrs = {"attr1": ["val1"], "attr2": ["val2-1", "val2-2"]}
  961. role_id = admin.create_realm_role(
  962. payload={"name": attribute_role, "attributes": test_attrs}, skip_exists=True
  963. )
  964. assert role_id, role_id
  965. cli_role_id = admin.create_client_role(
  966. client, payload={"name": attribute_role, "attributes": test_attrs}, skip_exists=True
  967. )
  968. assert cli_role_id, cli_role_id
  969. if not includes_attributes:
  970. test_attrs = None
  971. # tests
  972. roles = admin.get_realm_roles(**arg_brief_repr)
  973. roles_filtered = [role for role in roles if role["name"] == role_id]
  974. assert roles_filtered, roles_filtered
  975. role = roles_filtered[0]
  976. assert role.get("attributes") == test_attrs, testcase
  977. roles = admin.get_client_roles(client, **arg_brief_repr)
  978. roles_filtered = [role for role in roles if role["name"] == cli_role_id]
  979. assert roles_filtered, roles_filtered
  980. role = roles_filtered[0]
  981. assert role.get("attributes") == test_attrs, testcase
  982. # cleanup
  983. res = admin.delete_realm_role(role_name=attribute_role)
  984. assert res == dict(), res
  985. res = admin.delete_client_role(client, role_name=attribute_role)
  986. assert res == dict(), res
  987. def test_client_scope_realm_roles(admin: KeycloakAdmin, realm: str):
  988. """Test client realm roles.
  989. :param admin: Keycloak admin
  990. :type admin: KeycloakAdmin
  991. :param realm: Keycloak realm
  992. :type realm: str
  993. """
  994. admin.realm_name = realm
  995. # Test get realm roles
  996. roles = admin.get_realm_roles()
  997. assert len(roles) == 3, roles
  998. role_names = [x["name"] for x in roles]
  999. assert "uma_authorization" in role_names, role_names
  1000. assert "offline_access" in role_names, role_names
  1001. # create realm role for test
  1002. role_id = admin.create_realm_role(payload={"name": "test-realm-role"}, skip_exists=True)
  1003. assert role_id, role_id
  1004. # Test realm role client assignment
  1005. client_id = admin.create_client(
  1006. payload={"name": "role-testing-client", "clientId": "role-testing-client"}
  1007. )
  1008. with pytest.raises(KeycloakPostError) as err:
  1009. admin.assign_realm_roles_to_client_scope(client_id=client_id, roles=["bad"])
  1010. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1011. res = admin.assign_realm_roles_to_client_scope(
  1012. client_id=client_id,
  1013. roles=[
  1014. admin.get_realm_role(role_name="offline_access"),
  1015. admin.get_realm_role(role_name="test-realm-role"),
  1016. ],
  1017. )
  1018. assert res == dict(), res
  1019. roles = admin.get_realm_roles_of_client_scope(client_id=client_id)
  1020. assert len(roles) == 2
  1021. client_role_names = [x["name"] for x in roles]
  1022. assert "offline_access" in client_role_names, client_role_names
  1023. assert "test-realm-role" in client_role_names, client_role_names
  1024. assert "uma_authorization" not in client_role_names, client_role_names
  1025. # Test remove realm role of client
  1026. with pytest.raises(KeycloakDeleteError) as err:
  1027. admin.delete_realm_roles_of_client_scope(client_id=client_id, roles=["bad"])
  1028. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1029. res = admin.delete_realm_roles_of_client_scope(
  1030. client_id=client_id, roles=[admin.get_realm_role(role_name="offline_access")]
  1031. )
  1032. assert res == dict(), res
  1033. roles = admin.get_realm_roles_of_client_scope(client_id=client_id)
  1034. assert len(roles) == 1
  1035. assert "test-realm-role" in [x["name"] for x in roles]
  1036. res = admin.delete_realm_roles_of_client_scope(
  1037. client_id=client_id, roles=[admin.get_realm_role(role_name="test-realm-role")]
  1038. )
  1039. assert res == dict(), res
  1040. roles = admin.get_realm_roles_of_client_scope(client_id=client_id)
  1041. assert len(roles) == 0
  1042. def test_client_scope_client_roles(admin: KeycloakAdmin, realm: str, client: str):
  1043. """Test client assignment of other client roles.
  1044. :param admin: Keycloak admin
  1045. :type admin: KeycloakAdmin
  1046. :param realm: Keycloak realm
  1047. :type realm: str
  1048. :param client: Keycloak client
  1049. :type client: str
  1050. """
  1051. admin.realm_name = realm
  1052. client_id = admin.create_client(
  1053. payload={"name": "role-testing-client", "clientId": "role-testing-client"}
  1054. )
  1055. # Test get client roles
  1056. roles = admin.get_client_roles_of_client_scope(client_id, client)
  1057. assert len(roles) == 0, roles
  1058. # create client role for test
  1059. client_role_id = admin.create_client_role(
  1060. client_role_id=client, payload={"name": "client-role-test"}, skip_exists=True
  1061. )
  1062. assert client_role_id, client_role_id
  1063. # Test client role assignment to other client
  1064. with pytest.raises(KeycloakPostError) as err:
  1065. admin.assign_client_roles_to_client_scope(
  1066. client_id=client_id, client_roles_owner_id=client, roles=["bad"]
  1067. )
  1068. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1069. res = admin.assign_client_roles_to_client_scope(
  1070. client_id=client_id,
  1071. client_roles_owner_id=client,
  1072. roles=[admin.get_client_role(client_id=client, role_name="client-role-test")],
  1073. )
  1074. assert res == dict(), res
  1075. roles = admin.get_client_roles_of_client_scope(
  1076. client_id=client_id, client_roles_owner_id=client
  1077. )
  1078. assert len(roles) == 1
  1079. client_role_names = [x["name"] for x in roles]
  1080. assert "client-role-test" in client_role_names, client_role_names
  1081. # Test remove realm role of client
  1082. with pytest.raises(KeycloakDeleteError) as err:
  1083. admin.delete_client_roles_of_client_scope(
  1084. client_id=client_id, client_roles_owner_id=client, roles=["bad"]
  1085. )
  1086. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1087. res = admin.delete_client_roles_of_client_scope(
  1088. client_id=client_id,
  1089. client_roles_owner_id=client,
  1090. roles=[admin.get_client_role(client_id=client, role_name="client-role-test")],
  1091. )
  1092. assert res == dict(), res
  1093. roles = admin.get_client_roles_of_client_scope(
  1094. client_id=client_id, client_roles_owner_id=client
  1095. )
  1096. assert len(roles) == 0
  1097. def test_client_roles(admin: KeycloakAdmin, client: str):
  1098. """Test client roles.
  1099. :param admin: Keycloak Admin client
  1100. :type admin: KeycloakAdmin
  1101. :param client: Keycloak client
  1102. :type client: str
  1103. """
  1104. # Test get client roles
  1105. res = admin.get_client_roles(client_id=client)
  1106. assert len(res) == 0
  1107. with pytest.raises(KeycloakGetError) as err:
  1108. admin.get_client_roles(client_id="bad")
  1109. assert err.match('404: b\'{"error":"Could not find client"}\'')
  1110. # Test create client role
  1111. client_role_id = admin.create_client_role(
  1112. client_role_id=client, payload={"name": "client-role-test"}, skip_exists=True
  1113. )
  1114. with pytest.raises(KeycloakPostError) as err:
  1115. admin.create_client_role(client_role_id=client, payload={"name": "client-role-test"})
  1116. assert err.match('409: b\'{"errorMessage":"Role with name client-role-test already exists"}\'')
  1117. client_role_id_2 = admin.create_client_role(
  1118. client_role_id=client, payload={"name": "client-role-test"}, skip_exists=True
  1119. )
  1120. assert client_role_id == client_role_id_2
  1121. # Test get client role
  1122. res = admin.get_client_role(client_id=client, role_name="client-role-test")
  1123. assert res["name"] == client_role_id
  1124. with pytest.raises(KeycloakGetError) as err:
  1125. admin.get_client_role(client_id=client, role_name="bad")
  1126. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1127. res_ = admin.get_client_role_id(client_id=client, role_name="client-role-test")
  1128. assert res_ == res["id"]
  1129. with pytest.raises(KeycloakGetError) as err:
  1130. admin.get_client_role_id(client_id=client, role_name="bad")
  1131. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1132. assert len(admin.get_client_roles(client_id=client)) == 1
  1133. # Test update client role
  1134. res = admin.update_client_role(
  1135. client_role_id=client,
  1136. role_name="client-role-test",
  1137. payload={"name": "client-role-test-update"},
  1138. )
  1139. assert res == dict()
  1140. with pytest.raises(KeycloakPutError) as err:
  1141. res = admin.update_client_role(
  1142. client_role_id=client,
  1143. role_name="client-role-test",
  1144. payload={"name": "client-role-test-update"},
  1145. )
  1146. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1147. # Test user with client role
  1148. res = admin.get_client_role_members(client_id=client, role_name="client-role-test-update")
  1149. assert len(res) == 0
  1150. with pytest.raises(KeycloakGetError) as err:
  1151. admin.get_client_role_members(client_id=client, role_name="bad")
  1152. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1153. user_id = admin.create_user(payload={"username": "test", "email": "test@test.test"})
  1154. with pytest.raises(KeycloakPostError) as err:
  1155. admin.assign_client_role(user_id=user_id, client_id=client, roles=["bad"])
  1156. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1157. res = admin.assign_client_role(
  1158. user_id=user_id,
  1159. client_id=client,
  1160. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  1161. )
  1162. assert res == dict()
  1163. assert (
  1164. len(admin.get_client_role_members(client_id=client, role_name="client-role-test-update"))
  1165. == 1
  1166. )
  1167. roles = admin.get_client_roles_of_user(user_id=user_id, client_id=client)
  1168. assert len(roles) == 1, roles
  1169. with pytest.raises(KeycloakGetError) as err:
  1170. admin.get_client_roles_of_user(user_id=user_id, client_id="bad")
  1171. assert err.match('404: b\'{"error":"Client not found"}\'')
  1172. roles = admin.get_composite_client_roles_of_user(user_id=user_id, client_id=client)
  1173. assert len(roles) == 1, roles
  1174. with pytest.raises(KeycloakGetError) as err:
  1175. admin.get_composite_client_roles_of_user(user_id=user_id, client_id="bad")
  1176. assert err.match('404: b\'{"error":"Client not found"}\'')
  1177. roles = admin.get_available_client_roles_of_user(user_id=user_id, client_id=client)
  1178. assert len(roles) == 0, roles
  1179. with pytest.raises(KeycloakGetError) as err:
  1180. admin.get_composite_client_roles_of_user(user_id=user_id, client_id="bad")
  1181. assert err.match('404: b\'{"error":"Client not found"}\'')
  1182. with pytest.raises(KeycloakDeleteError) as err:
  1183. admin.delete_client_roles_of_user(user_id=user_id, client_id=client, roles=["bad"])
  1184. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1185. admin.delete_client_roles_of_user(
  1186. user_id=user_id,
  1187. client_id=client,
  1188. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  1189. )
  1190. assert len(admin.get_client_roles_of_user(user_id=user_id, client_id=client)) == 0
  1191. # Test groups and client roles
  1192. res = admin.get_client_role_groups(client_id=client, role_name="client-role-test-update")
  1193. assert len(res) == 0
  1194. with pytest.raises(KeycloakGetError) as err:
  1195. admin.get_client_role_groups(client_id=client, role_name="bad")
  1196. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1197. group_id = admin.create_group(payload={"name": "test-group"})
  1198. res = admin.get_group_client_roles(group_id=group_id, client_id=client)
  1199. assert len(res) == 0
  1200. with pytest.raises(KeycloakGetError) as err:
  1201. admin.get_group_client_roles(group_id=group_id, client_id="bad")
  1202. assert err.match('404: b\'{"error":"Client not found"}\'')
  1203. with pytest.raises(KeycloakPostError) as err:
  1204. admin.assign_group_client_roles(group_id=group_id, client_id=client, roles=["bad"])
  1205. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1206. res = admin.assign_group_client_roles(
  1207. group_id=group_id,
  1208. client_id=client,
  1209. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  1210. )
  1211. assert res == dict()
  1212. assert (
  1213. len(admin.get_client_role_groups(client_id=client, role_name="client-role-test-update"))
  1214. == 1
  1215. )
  1216. assert len(admin.get_group_client_roles(group_id=group_id, client_id=client)) == 1
  1217. with pytest.raises(KeycloakDeleteError) as err:
  1218. admin.delete_group_client_roles(group_id=group_id, client_id=client, roles=["bad"])
  1219. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1220. res = admin.delete_group_client_roles(
  1221. group_id=group_id,
  1222. client_id=client,
  1223. roles=[admin.get_client_role(client_id=client, role_name="client-role-test-update")],
  1224. )
  1225. assert res == dict()
  1226. # Test composite client roles
  1227. with pytest.raises(KeycloakPostError) as err:
  1228. admin.add_composite_client_roles_to_role(
  1229. client_role_id=client, role_name="client-role-test-update", roles=["bad"]
  1230. )
  1231. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1232. res = admin.add_composite_client_roles_to_role(
  1233. client_role_id=client,
  1234. role_name="client-role-test-update",
  1235. roles=[admin.get_realm_role(role_name="offline_access")],
  1236. )
  1237. assert res == dict()
  1238. assert admin.get_client_role(client_id=client, role_name="client-role-test-update")[
  1239. "composite"
  1240. ]
  1241. # Test delete of client role
  1242. res = admin.delete_client_role(client_role_id=client, role_name="client-role-test-update")
  1243. assert res == dict()
  1244. with pytest.raises(KeycloakDeleteError) as err:
  1245. admin.delete_client_role(client_role_id=client, role_name="client-role-test-update")
  1246. assert err.match('404: b\'{"error":"Could not find role"}\'')
  1247. def test_enable_token_exchange(admin: KeycloakAdmin, realm: str):
  1248. """Test enable token exchange.
  1249. :param admin: Keycloak Admin client
  1250. :type admin: KeycloakAdmin
  1251. :param realm: Keycloak realm
  1252. :type realm: str
  1253. :raises AssertionError: In case of bad configuration
  1254. """
  1255. # Test enabling token exchange between two confidential clients
  1256. admin.realm_name = realm
  1257. # Create test clients
  1258. source_client_id = admin.create_client(
  1259. payload={"name": "Source Client", "clientId": "source-client"}
  1260. )
  1261. target_client_id = admin.create_client(
  1262. payload={"name": "Target Client", "clientId": "target-client"}
  1263. )
  1264. for c in admin.get_clients():
  1265. if c["clientId"] == "realm-management":
  1266. realm_management_id = c["id"]
  1267. break
  1268. else:
  1269. raise AssertionError("Missing realm management client")
  1270. # Enable permissions on the Superset client
  1271. admin.update_client_management_permissions(
  1272. payload={"enabled": True}, client_id=target_client_id
  1273. )
  1274. # Fetch various IDs and strings needed when creating the permission
  1275. token_exchange_permission_id = admin.get_client_management_permissions(
  1276. client_id=target_client_id
  1277. )["scopePermissions"]["token-exchange"]
  1278. scopes = admin.get_client_authz_policy_scopes(
  1279. client_id=realm_management_id, policy_id=token_exchange_permission_id
  1280. )
  1281. for s in scopes:
  1282. if s["name"] == "token-exchange":
  1283. token_exchange_scope_id = s["id"]
  1284. break
  1285. else:
  1286. raise AssertionError("Missing token-exchange scope")
  1287. resources = admin.get_client_authz_policy_resources(
  1288. client_id=realm_management_id, policy_id=token_exchange_permission_id
  1289. )
  1290. for r in resources:
  1291. if r["name"] == f"client.resource.{target_client_id}":
  1292. token_exchange_resource_id = r["_id"]
  1293. break
  1294. else:
  1295. raise AssertionError("Missing client resource")
  1296. # Create a client policy for source client
  1297. policy_name = "Exchange source client token with target client token"
  1298. client_policy_id = admin.create_client_authz_client_policy(
  1299. payload={
  1300. "type": "client",
  1301. "logic": "POSITIVE",
  1302. "decisionStrategy": "UNANIMOUS",
  1303. "name": policy_name,
  1304. "clients": [source_client_id],
  1305. },
  1306. client_id=realm_management_id,
  1307. )["id"]
  1308. policies = admin.get_client_authz_client_policies(client_id=realm_management_id)
  1309. for policy in policies:
  1310. if policy["name"] == policy_name:
  1311. assert policy["clients"] == [source_client_id]
  1312. break
  1313. else:
  1314. raise AssertionError("Missing client policy")
  1315. # Update permissions on the target client to reference this policy
  1316. permission_name = admin.get_client_authz_scope_permission(
  1317. client_id=realm_management_id, scope_id=token_exchange_permission_id
  1318. )["name"]
  1319. admin.update_client_authz_scope_permission(
  1320. payload={
  1321. "id": token_exchange_permission_id,
  1322. "name": permission_name,
  1323. "type": "scope",
  1324. "logic": "POSITIVE",
  1325. "decisionStrategy": "UNANIMOUS",
  1326. "resources": [token_exchange_resource_id],
  1327. "scopes": [token_exchange_scope_id],
  1328. "policies": [client_policy_id],
  1329. },
  1330. client_id=realm_management_id,
  1331. scope_id=token_exchange_permission_id,
  1332. )
  1333. def test_email(admin: KeycloakAdmin, user: str):
  1334. """Test email.
  1335. :param admin: Keycloak Admin client
  1336. :type admin: KeycloakAdmin
  1337. :param user: Keycloak user
  1338. :type user: str
  1339. """
  1340. # Emails will fail as we don't have SMTP test setup
  1341. with pytest.raises(KeycloakPutError) as err:
  1342. admin.send_update_account(user_id=user, payload=dict())
  1343. assert err.match('500: b\'{"error":"unknown_error"}\'')
  1344. admin.update_user(user_id=user, payload={"enabled": True})
  1345. with pytest.raises(KeycloakPutError) as err:
  1346. admin.send_verify_email(user_id=user)
  1347. assert err.match('500: b\'{"errorMessage":"Failed to send execute actions email"}\'')
  1348. def test_get_sessions(admin: KeycloakAdmin):
  1349. """Test get sessions.
  1350. :param admin: Keycloak Admin client
  1351. :type admin: KeycloakAdmin
  1352. """
  1353. sessions = admin.get_sessions(user_id=admin.get_user_id(username=admin.username))
  1354. assert len(sessions) >= 1
  1355. with pytest.raises(KeycloakGetError) as err:
  1356. admin.get_sessions(user_id="bad")
  1357. assert err.match('404: b\'{"error":"User not found"}\'')
  1358. def test_get_client_installation_provider(admin: KeycloakAdmin, client: str):
  1359. """Test get client installation provider.
  1360. :param admin: Keycloak Admin client
  1361. :type admin: KeycloakAdmin
  1362. :param client: Keycloak client
  1363. :type client: str
  1364. """
  1365. with pytest.raises(KeycloakGetError) as err:
  1366. admin.get_client_installation_provider(client_id=client, provider_id="bad")
  1367. assert err.match('404: b\'{"error":"Unknown Provider"}\'')
  1368. installation = admin.get_client_installation_provider(
  1369. client_id=client, provider_id="keycloak-oidc-keycloak-json"
  1370. )
  1371. assert set(installation.keys()) == {
  1372. "auth-server-url",
  1373. "confidential-port",
  1374. "credentials",
  1375. "realm",
  1376. "resource",
  1377. "ssl-required",
  1378. }
  1379. def test_auth_flows(admin: KeycloakAdmin, realm: str):
  1380. """Test auth flows.
  1381. :param admin: Keycloak Admin client
  1382. :type admin: KeycloakAdmin
  1383. :param realm: Keycloak realm
  1384. :type realm: str
  1385. """
  1386. admin.realm_name = realm
  1387. res = admin.get_authentication_flows()
  1388. assert len(res) == 8, res
  1389. assert set(res[0].keys()) == {
  1390. "alias",
  1391. "authenticationExecutions",
  1392. "builtIn",
  1393. "description",
  1394. "id",
  1395. "providerId",
  1396. "topLevel",
  1397. }
  1398. assert {x["alias"] for x in res} == {
  1399. "reset credentials",
  1400. "browser",
  1401. "http challenge",
  1402. "registration",
  1403. "docker auth",
  1404. "direct grant",
  1405. "first broker login",
  1406. "clients",
  1407. }
  1408. with pytest.raises(KeycloakGetError) as err:
  1409. admin.get_authentication_flow_for_id(flow_id="bad")
  1410. assert err.match('404: b\'{"error":"Could not find flow with id"}\'')
  1411. browser_flow_id = [x for x in res if x["alias"] == "browser"][0]["id"]
  1412. res = admin.get_authentication_flow_for_id(flow_id=browser_flow_id)
  1413. assert res["alias"] == "browser"
  1414. # Test copying
  1415. with pytest.raises(KeycloakPostError) as err:
  1416. admin.copy_authentication_flow(payload=dict(), flow_alias="bad")
  1417. assert err.match("404: b''")
  1418. res = admin.copy_authentication_flow(payload={"newName": "test-browser"}, flow_alias="browser")
  1419. assert res == b"", res
  1420. assert len(admin.get_authentication_flows()) == 9
  1421. # Test create
  1422. res = admin.create_authentication_flow(
  1423. payload={"alias": "test-create", "providerId": "basic-flow"}
  1424. )
  1425. assert res == b""
  1426. with pytest.raises(KeycloakPostError) as err:
  1427. admin.create_authentication_flow(payload={"alias": "test-create", "builtIn": False})
  1428. assert err.match('409: b\'{"errorMessage":"Flow test-create already exists"}\'')
  1429. assert admin.create_authentication_flow(
  1430. payload={"alias": "test-create"}, skip_exists=True
  1431. ) == {"msg": "Already exists"}
  1432. # Test flow executions
  1433. res = admin.get_authentication_flow_executions(flow_alias="browser")
  1434. assert len(res) == 8, res
  1435. with pytest.raises(KeycloakGetError) as err:
  1436. admin.get_authentication_flow_executions(flow_alias="bad")
  1437. assert err.match("404: b''")
  1438. exec_id = res[0]["id"]
  1439. res = admin.get_authentication_flow_execution(execution_id=exec_id)
  1440. assert set(res.keys()) == {
  1441. "alternative",
  1442. "authenticator",
  1443. "authenticatorFlow",
  1444. "conditional",
  1445. "disabled",
  1446. "enabled",
  1447. "id",
  1448. "parentFlow",
  1449. "priority",
  1450. "required",
  1451. "requirement",
  1452. }, res
  1453. with pytest.raises(KeycloakGetError) as err:
  1454. admin.get_authentication_flow_execution(execution_id="bad")
  1455. assert err.match('404: b\'{"error":"Illegal execution"}\'')
  1456. with pytest.raises(KeycloakPostError) as err:
  1457. admin.create_authentication_flow_execution(payload=dict(), flow_alias="browser")
  1458. assert err.match('400: b\'{"error":"It is illegal to add execution to a built in flow"}\'')
  1459. res = admin.create_authentication_flow_execution(
  1460. payload={"provider": "auth-cookie"}, flow_alias="test-create"
  1461. )
  1462. assert res == b""
  1463. assert len(admin.get_authentication_flow_executions(flow_alias="test-create")) == 1
  1464. with pytest.raises(KeycloakPutError) as err:
  1465. admin.update_authentication_flow_executions(
  1466. payload={"required": "yes"}, flow_alias="test-create"
  1467. )
  1468. assert err.match('400: b\'{"error":"Unrecognized field')
  1469. payload = admin.get_authentication_flow_executions(flow_alias="test-create")[0]
  1470. payload["displayName"] = "test"
  1471. res = admin.update_authentication_flow_executions(payload=payload, flow_alias="test-create")
  1472. assert res
  1473. exec_id = admin.get_authentication_flow_executions(flow_alias="test-create")[0]["id"]
  1474. res = admin.delete_authentication_flow_execution(execution_id=exec_id)
  1475. assert res == dict()
  1476. with pytest.raises(KeycloakDeleteError) as err:
  1477. admin.delete_authentication_flow_execution(execution_id=exec_id)
  1478. assert err.match('404: b\'{"error":"Illegal execution"}\'')
  1479. # Test subflows
  1480. res = admin.create_authentication_flow_subflow(
  1481. payload={
  1482. "alias": "test-subflow",
  1483. "provider": "basic-flow",
  1484. "type": "something",
  1485. "description": "something",
  1486. },
  1487. flow_alias="test-browser",
  1488. )
  1489. assert res == b""
  1490. with pytest.raises(KeycloakPostError) as err:
  1491. admin.create_authentication_flow_subflow(
  1492. payload={"alias": "test-subflow", "providerId": "basic-flow"},
  1493. flow_alias="test-browser",
  1494. )
  1495. assert err.match('409: b\'{"errorMessage":"New flow alias name already exists"}\'')
  1496. res = admin.create_authentication_flow_subflow(
  1497. payload={
  1498. "alias": "test-subflow",
  1499. "provider": "basic-flow",
  1500. "type": "something",
  1501. "description": "something",
  1502. },
  1503. flow_alias="test-create",
  1504. skip_exists=True,
  1505. )
  1506. assert res == {"msg": "Already exists"}
  1507. # Test delete auth flow
  1508. flow_id = [x for x in admin.get_authentication_flows() if x["alias"] == "test-browser"][0][
  1509. "id"
  1510. ]
  1511. res = admin.delete_authentication_flow(flow_id=flow_id)
  1512. assert res == dict()
  1513. with pytest.raises(KeycloakDeleteError) as err:
  1514. admin.delete_authentication_flow(flow_id=flow_id)
  1515. assert err.match('404: b\'{"error":"Could not find flow with id"}\'')
  1516. def test_authentication_configs(admin: KeycloakAdmin, realm: str):
  1517. """Test authentication configs.
  1518. :param admin: Keycloak Admin client
  1519. :type admin: KeycloakAdmin
  1520. :param realm: Keycloak realm
  1521. :type realm: str
  1522. """
  1523. admin.realm_name = realm
  1524. # Test list of auth providers
  1525. res = admin.get_authenticator_providers()
  1526. assert len(res) == 38
  1527. res = admin.get_authenticator_provider_config_description(provider_id="auth-cookie")
  1528. assert res == {
  1529. "helpText": "Validates the SSO cookie set by the auth server.",
  1530. "name": "Cookie",
  1531. "properties": [],
  1532. "providerId": "auth-cookie",
  1533. }
  1534. # Test authenticator config
  1535. # Currently unable to find a sustainable way to fetch the config id,
  1536. # therefore testing only failures
  1537. with pytest.raises(KeycloakGetError) as err:
  1538. admin.get_authenticator_config(config_id="bad")
  1539. assert err.match('404: b\'{"error":"Could not find authenticator config"}\'')
  1540. with pytest.raises(KeycloakPutError) as err:
  1541. admin.update_authenticator_config(payload=dict(), config_id="bad")
  1542. assert err.match('404: b\'{"error":"Could not find authenticator config"}\'')
  1543. with pytest.raises(KeycloakDeleteError) as err:
  1544. admin.delete_authenticator_config(config_id="bad")
  1545. assert err.match('404: b\'{"error":"Could not find authenticator config"}\'')
  1546. def test_sync_users(admin: KeycloakAdmin, realm: str):
  1547. """Test sync users.
  1548. :param admin: Keycloak Admin client
  1549. :type admin: KeycloakAdmin
  1550. :param realm: Keycloak realm
  1551. :type realm: str
  1552. """
  1553. admin.realm_name = realm
  1554. # Only testing the error message
  1555. with pytest.raises(KeycloakPostError) as err:
  1556. admin.sync_users(storage_id="does-not-exist", action="triggerFullSync")
  1557. assert err.match('404: b\'{"error":"Could not find component"}\'')
  1558. def test_client_scopes(admin: KeycloakAdmin, realm: str):
  1559. """Test client scopes.
  1560. :param admin: Keycloak Admin client
  1561. :type admin: KeycloakAdmin
  1562. :param realm: Keycloak realm
  1563. :type realm: str
  1564. """
  1565. admin.realm_name = realm
  1566. # Test get client scopes
  1567. res = admin.get_client_scopes()
  1568. scope_names = {x["name"] for x in res}
  1569. assert len(res) == 10
  1570. assert "email" in scope_names
  1571. assert "profile" in scope_names
  1572. assert "offline_access" in scope_names
  1573. with pytest.raises(KeycloakGetError) as err:
  1574. admin.get_client_scope(client_scope_id="does-not-exist")
  1575. assert err.match('404: b\'{"error":"Could not find client scope"}\'')
  1576. scope = admin.get_client_scope(client_scope_id=res[0]["id"])
  1577. assert res[0] == scope
  1578. scope = admin.get_client_scope_by_name(client_scope_name=res[0]["name"])
  1579. assert res[0] == scope
  1580. # Test create client scope
  1581. res = admin.create_client_scope(payload={"name": "test-scope"}, skip_exists=True)
  1582. assert res
  1583. res2 = admin.create_client_scope(payload={"name": "test-scope"}, skip_exists=True)
  1584. assert res == res2
  1585. with pytest.raises(KeycloakPostError) as err:
  1586. admin.create_client_scope(payload={"name": "test-scope"}, skip_exists=False)
  1587. assert err.match('409: b\'{"errorMessage":"Client Scope test-scope already exists"}\'')
  1588. # Test update client scope
  1589. with pytest.raises(KeycloakPutError) as err:
  1590. admin.update_client_scope(client_scope_id="does-not-exist", payload=dict())
  1591. assert err.match('404: b\'{"error":"Could not find client scope"}\'')
  1592. res_update = admin.update_client_scope(
  1593. client_scope_id=res, payload={"name": "test-scope-update"}
  1594. )
  1595. assert res_update == dict()
  1596. admin.get_client_scope(client_scope_id=res)["name"] == "test-scope-update"
  1597. # Test get mappers
  1598. mappers = admin.get_mappers_from_client_scope(client_scope_id=res)
  1599. assert mappers == list()
  1600. # Test add mapper
  1601. with pytest.raises(KeycloakPostError) as err:
  1602. admin.add_mapper_to_client_scope(client_scope_id=res, payload=dict())
  1603. assert err.match('404: b\'{"error":"ProtocolMapper provider not found"}\'')
  1604. res_add = admin.add_mapper_to_client_scope(
  1605. client_scope_id=res,
  1606. payload={
  1607. "name": "test-mapper",
  1608. "protocol": "openid-connect",
  1609. "protocolMapper": "oidc-usermodel-attribute-mapper",
  1610. },
  1611. )
  1612. assert res_add == b""
  1613. assert len(admin.get_mappers_from_client_scope(client_scope_id=res)) == 1
  1614. # Test update mapper
  1615. test_mapper = admin.get_mappers_from_client_scope(client_scope_id=res)[0]
  1616. with pytest.raises(KeycloakPutError) as err:
  1617. admin.update_mapper_in_client_scope(
  1618. client_scope_id="does-not-exist", protocol_mapper_id=test_mapper["id"], payload=dict()
  1619. )
  1620. assert err.match('404: b\'{"error":"Could not find client scope"}\'')
  1621. test_mapper["config"]["user.attribute"] = "test"
  1622. res_update = admin.update_mapper_in_client_scope(
  1623. client_scope_id=res, protocol_mapper_id=test_mapper["id"], payload=test_mapper
  1624. )
  1625. assert res_update == dict()
  1626. assert (
  1627. admin.get_mappers_from_client_scope(client_scope_id=res)[0]["config"]["user.attribute"]
  1628. == "test"
  1629. )
  1630. # Test delete mapper
  1631. res_del = admin.delete_mapper_from_client_scope(
  1632. client_scope_id=res, protocol_mapper_id=test_mapper["id"]
  1633. )
  1634. assert res_del == dict()
  1635. with pytest.raises(KeycloakDeleteError) as err:
  1636. admin.delete_mapper_from_client_scope(
  1637. client_scope_id=res, protocol_mapper_id=test_mapper["id"]
  1638. )
  1639. assert err.match('404: b\'{"error":"Model not found"}\'')
  1640. # Test default default scopes
  1641. res_defaults = admin.get_default_default_client_scopes()
  1642. assert len(res_defaults) == 6
  1643. with pytest.raises(KeycloakPutError) as err:
  1644. admin.add_default_default_client_scope(scope_id="does-not-exist")
  1645. assert err.match('404: b\'{"error":"Client scope not found"}\'')
  1646. res_add = admin.add_default_default_client_scope(scope_id=res)
  1647. assert res_add == dict()
  1648. assert len(admin.get_default_default_client_scopes()) == 7
  1649. with pytest.raises(KeycloakDeleteError) as err:
  1650. admin.delete_default_default_client_scope(scope_id="does-not-exist")
  1651. assert err.match('404: b\'{"error":"Client scope not found"}\'')
  1652. res_del = admin.delete_default_default_client_scope(scope_id=res)
  1653. assert res_del == dict()
  1654. assert len(admin.get_default_default_client_scopes()) == 6
  1655. # Test default optional scopes
  1656. res_defaults = admin.get_default_optional_client_scopes()
  1657. assert len(res_defaults) == 4
  1658. with pytest.raises(KeycloakPutError) as err:
  1659. admin.add_default_optional_client_scope(scope_id="does-not-exist")
  1660. assert err.match('404: b\'{"error":"Client scope not found"}\'')
  1661. res_add = admin.add_default_optional_client_scope(scope_id=res)
  1662. assert res_add == dict()
  1663. assert len(admin.get_default_optional_client_scopes()) == 5
  1664. with pytest.raises(KeycloakDeleteError) as err:
  1665. admin.delete_default_optional_client_scope(scope_id="does-not-exist")
  1666. assert err.match('404: b\'{"error":"Client scope not found"}\'')
  1667. res_del = admin.delete_default_optional_client_scope(scope_id=res)
  1668. assert res_del == dict()
  1669. assert len(admin.get_default_optional_client_scopes()) == 4
  1670. # Test client scope delete
  1671. res_del = admin.delete_client_scope(client_scope_id=res)
  1672. assert res_del == dict()
  1673. with pytest.raises(KeycloakDeleteError) as err:
  1674. admin.delete_client_scope(client_scope_id=res)
  1675. assert err.match('404: b\'{"error":"Could not find client scope"}\'')
  1676. def test_components(admin: KeycloakAdmin, realm: str):
  1677. """Test components.
  1678. :param admin: Keycloak Admin client
  1679. :type admin: KeycloakAdmin
  1680. :param realm: Keycloak realm
  1681. :type realm: str
  1682. """
  1683. admin.realm_name = realm
  1684. # Test get components
  1685. res = admin.get_components()
  1686. assert len(res) == 12
  1687. with pytest.raises(KeycloakGetError) as err:
  1688. admin.get_component(component_id="does-not-exist")
  1689. assert err.match('404: b\'{"error":"Could not find component"}\'')
  1690. res_get = admin.get_component(component_id=res[0]["id"])
  1691. assert res_get == res[0]
  1692. # Test create component
  1693. with pytest.raises(KeycloakPostError) as err:
  1694. admin.create_component(payload={"bad": "dict"})
  1695. assert err.match('400: b\'{"error":"Unrecognized field')
  1696. res = admin.create_component(
  1697. payload={
  1698. "name": "Test Component",
  1699. "providerId": "max-clients",
  1700. "providerType": "org.keycloak.services.clientregistration."
  1701. + "policy.ClientRegistrationPolicy",
  1702. "config": {"max-clients": ["1000"]},
  1703. }
  1704. )
  1705. assert res
  1706. assert admin.get_component(component_id=res)["name"] == "Test Component"
  1707. # Test update component
  1708. component = admin.get_component(component_id=res)
  1709. component["name"] = "Test Component Update"
  1710. with pytest.raises(KeycloakPutError) as err:
  1711. admin.update_component(component_id="does-not-exist", payload=dict())
  1712. assert err.match('404: b\'{"error":"Could not find component"}\'')
  1713. res_upd = admin.update_component(component_id=res, payload=component)
  1714. assert res_upd == dict()
  1715. assert admin.get_component(component_id=res)["name"] == "Test Component Update"
  1716. # Test delete component
  1717. res_del = admin.delete_component(component_id=res)
  1718. assert res_del == dict()
  1719. with pytest.raises(KeycloakDeleteError) as err:
  1720. admin.delete_component(component_id=res)
  1721. assert err.match('404: b\'{"error":"Could not find component"}\'')
  1722. def test_keys(admin: KeycloakAdmin, realm: str):
  1723. """Test keys.
  1724. :param admin: Keycloak Admin client
  1725. :type admin: KeycloakAdmin
  1726. :param realm: Keycloak realm
  1727. :type realm: str
  1728. """
  1729. admin.realm_name = realm
  1730. assert set(admin.get_keys()["active"].keys()) == {"AES", "HS256", "RS256", "RSA-OAEP"}
  1731. assert {k["algorithm"] for k in admin.get_keys()["keys"]} == {
  1732. "HS256",
  1733. "RSA-OAEP",
  1734. "AES",
  1735. "RS256",
  1736. }
  1737. def test_events(admin: KeycloakAdmin, realm: str):
  1738. """Test events.
  1739. :param admin: Keycloak Admin client
  1740. :type admin: KeycloakAdmin
  1741. :param realm: Keycloak realm
  1742. :type realm: str
  1743. """
  1744. admin.realm_name = realm
  1745. events = admin.get_events()
  1746. assert events == list()
  1747. with pytest.raises(KeycloakPutError) as err:
  1748. admin.set_events(payload={"bad": "conf"})
  1749. assert err.match('400: b\'{"error":"Unrecognized field')
  1750. res = admin.set_events(payload={"adminEventsDetailsEnabled": True, "adminEventsEnabled": True})
  1751. assert res == dict()
  1752. admin.create_client(payload={"name": "test", "clientId": "test"})
  1753. events = admin.get_events()
  1754. assert events == list()
  1755. def test_auto_refresh(admin: KeycloakAdmin, realm: str):
  1756. """Test auto refresh token.
  1757. :param admin: Keycloak Admin client
  1758. :type admin: KeycloakAdmin
  1759. :param realm: Keycloak realm
  1760. :type realm: str
  1761. """
  1762. # Test get refresh
  1763. admin.auto_refresh_token = list()
  1764. admin.connection = ConnectionManager(
  1765. base_url=admin.server_url,
  1766. headers={"Authorization": "Bearer bad", "Content-Type": "application/json"},
  1767. timeout=60,
  1768. verify=admin.verify,
  1769. )
  1770. with pytest.raises(KeycloakAuthenticationError) as err:
  1771. admin.get_realm(realm_name=realm)
  1772. assert err.match('401: b\'{"error":"HTTP 401 Unauthorized"}\'')
  1773. admin.auto_refresh_token = ["get"]
  1774. del admin.token["refresh_token"]
  1775. assert admin.get_realm(realm_name=realm)
  1776. # Test bad refresh token
  1777. admin.connection = ConnectionManager(
  1778. base_url=admin.server_url,
  1779. headers={"Authorization": "Bearer bad", "Content-Type": "application/json"},
  1780. timeout=60,
  1781. verify=admin.verify,
  1782. )
  1783. admin.token["refresh_token"] = "bad"
  1784. with pytest.raises(KeycloakPostError) as err:
  1785. admin.get_realm(realm_name="test-refresh")
  1786. assert err.match(
  1787. '400: b\'{"error":"invalid_grant","error_description":"Invalid refresh token"}\''
  1788. )
  1789. admin.realm_name = "master"
  1790. admin.get_token()
  1791. admin.realm_name = realm
  1792. # Test post refresh
  1793. admin.connection = ConnectionManager(
  1794. base_url=admin.server_url,
  1795. headers={"Authorization": "Bearer bad", "Content-Type": "application/json"},
  1796. timeout=60,
  1797. verify=admin.verify,
  1798. )
  1799. with pytest.raises(KeycloakAuthenticationError) as err:
  1800. admin.create_realm(payload={"realm": "test-refresh"})
  1801. assert err.match('401: b\'{"error":"HTTP 401 Unauthorized"}\'')
  1802. admin.auto_refresh_token = ["get", "post"]
  1803. admin.realm_name = "master"
  1804. admin.user_logout(user_id=admin.get_user_id(username=admin.username))
  1805. assert admin.create_realm(payload={"realm": "test-refresh"}) == b""
  1806. admin.realm_name = realm
  1807. # Test update refresh
  1808. admin.connection = ConnectionManager(
  1809. base_url=admin.server_url,
  1810. headers={"Authorization": "Bearer bad", "Content-Type": "application/json"},
  1811. timeout=60,
  1812. verify=admin.verify,
  1813. )
  1814. with pytest.raises(KeycloakAuthenticationError) as err:
  1815. admin.update_realm(realm_name="test-refresh", payload={"accountTheme": "test"})
  1816. assert err.match('401: b\'{"error":"HTTP 401 Unauthorized"}\'')
  1817. admin.auto_refresh_token = ["get", "post", "put"]
  1818. assert (
  1819. admin.update_realm(realm_name="test-refresh", payload={"accountTheme": "test"}) == dict()
  1820. )
  1821. # Test delete refresh
  1822. admin.connection = ConnectionManager(
  1823. base_url=admin.server_url,
  1824. headers={"Authorization": "Bearer bad", "Content-Type": "application/json"},
  1825. timeout=60,
  1826. verify=admin.verify,
  1827. )
  1828. with pytest.raises(KeycloakAuthenticationError) as err:
  1829. admin.delete_realm(realm_name="test-refresh")
  1830. assert err.match('401: b\'{"error":"HTTP 401 Unauthorized"}\'')
  1831. admin.auto_refresh_token = ["get", "post", "put", "delete"]
  1832. assert admin.delete_realm(realm_name="test-refresh") == dict()
  1833. def test_get_required_actions(admin: KeycloakAdmin, realm: str):
  1834. """Test required actions.
  1835. :param admin: Keycloak Admin client
  1836. :type admin: KeycloakAdmin
  1837. :param realm: Keycloak realm
  1838. :type realm: str
  1839. """
  1840. admin.realm_name = realm
  1841. ractions = admin.get_required_actions()
  1842. assert isinstance(ractions, list)
  1843. for ra in ractions:
  1844. for key in [
  1845. "alias",
  1846. "name",
  1847. "providerId",
  1848. "enabled",
  1849. "defaultAction",
  1850. "priority",
  1851. "config",
  1852. ]:
  1853. assert key in ra
  1854. def test_get_required_action_by_alias(admin: KeycloakAdmin, realm: str):
  1855. """Test get required action by alias.
  1856. :param admin: Keycloak Admin client
  1857. :type admin: KeycloakAdmin
  1858. :param realm: Keycloak realm
  1859. :type realm: str
  1860. """
  1861. admin.realm_name = realm
  1862. ractions = admin.get_required_actions()
  1863. ra = admin.get_required_action_by_alias("UPDATE_PASSWORD")
  1864. assert ra in ractions
  1865. assert ra["alias"] == "UPDATE_PASSWORD"
  1866. assert admin.get_required_action_by_alias("does-not-exist") is None
  1867. def test_update_required_action(admin: KeycloakAdmin, realm: str):
  1868. """Test update required action.
  1869. :param admin: Keycloak Admin client
  1870. :type admin: KeycloakAdmin
  1871. :param realm: Keycloak realm
  1872. :type realm: str
  1873. """
  1874. admin.realm_name = realm
  1875. ra = admin.get_required_action_by_alias("UPDATE_PASSWORD")
  1876. old = copy.deepcopy(ra)
  1877. ra["enabled"] = False
  1878. admin.update_required_action("UPDATE_PASSWORD", ra)
  1879. newra = admin.get_required_action_by_alias("UPDATE_PASSWORD")
  1880. assert old != newra
  1881. assert newra["enabled"] is False
  1882. def test_get_composite_client_roles_of_group(
  1883. admin: KeycloakAdmin, realm: str, client: str, group: str, composite_client_role: str
  1884. ):
  1885. """Test get composite client roles of group.
  1886. :param admin: Keycloak Admin client
  1887. :type admin: KeycloakAdmin
  1888. :param realm: Keycloak realm
  1889. :type realm: str
  1890. :param client: Keycloak client
  1891. :type client: str
  1892. :param group: Keycloak group
  1893. :type group: str
  1894. :param composite_client_role: Composite client role
  1895. :type composite_client_role: str
  1896. """
  1897. admin.realm_name = realm
  1898. role = admin.get_client_role(client, composite_client_role)
  1899. admin.assign_group_client_roles(group_id=group, client_id=client, roles=[role])
  1900. result = admin.get_composite_client_roles_of_group(client, group)
  1901. assert role["id"] in [x["id"] for x in result]
  1902. def test_get_role_client_level_children(
  1903. admin: KeycloakAdmin, realm: str, client: str, composite_client_role: str, client_role: str
  1904. ):
  1905. """Test get children of composite client role.
  1906. :param admin: Keycloak Admin client
  1907. :type admin: KeycloakAdmin
  1908. :param realm: Keycloak realm
  1909. :type realm: str
  1910. :param client: Keycloak client
  1911. :type client: str
  1912. :param composite_client_role: Composite client role
  1913. :type composite_client_role: str
  1914. :param client_role: Client role
  1915. :type client_role: str
  1916. """
  1917. admin.realm_name = realm
  1918. child = admin.get_client_role(client, client_role)
  1919. parent = admin.get_client_role(client, composite_client_role)
  1920. res = admin.get_role_client_level_children(client, parent["id"])
  1921. assert child["id"] in [x["id"] for x in res]
  1922. def test_upload_certificate(admin: KeycloakAdmin, realm: str, client: str, selfsigned_cert: tuple):
  1923. """Test upload certificate.
  1924. :param admin: Keycloak Admin client
  1925. :type admin: KeycloakAdmin
  1926. :param realm: Keycloak realm
  1927. :type realm: str
  1928. :param client: Keycloak client
  1929. :type client: str
  1930. :param selfsigned_cert: Selfsigned certificates
  1931. :type selfsigned_cert: tuple
  1932. """
  1933. admin.realm_name = realm
  1934. cert, _ = selfsigned_cert
  1935. cert = cert.decode("utf-8").strip()
  1936. admin.upload_certificate(client, cert)
  1937. cl = admin.get_client(client)
  1938. assert cl["attributes"]["jwt.credential.certificate"] == "".join(cert.splitlines()[1:-1])
  1939. def test_get_bruteforce_status_for_user(
  1940. admin: KeycloakAdmin, oid_with_credentials: Tuple[KeycloakOpenID, str, str], realm: str
  1941. ):
  1942. """Test users.
  1943. :param admin: Keycloak Admin client
  1944. :type admin: KeycloakAdmin
  1945. :param oid_with_credentials: Keycloak OpenID client with pre-configured user credentials
  1946. :type oid_with_credentials: Tuple[KeycloakOpenID, str, str]
  1947. :param realm: Keycloak realm
  1948. :type realm: str
  1949. """
  1950. oid, username, password = oid_with_credentials
  1951. admin.realm_name = realm
  1952. # Turn on bruteforce protection
  1953. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": True})
  1954. res = admin.get_realm(realm_name=realm)
  1955. assert res["bruteForceProtected"] is True
  1956. # Test login user with wrong credentials
  1957. try:
  1958. oid.token(username=username, password="wrongpassword")
  1959. except KeycloakAuthenticationError:
  1960. pass
  1961. user_id = admin.get_user_id(username)
  1962. bruteforce_status = admin.get_bruteforce_detection_status(user_id)
  1963. assert bruteforce_status["numFailures"] == 1
  1964. # Cleanup
  1965. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": False})
  1966. res = admin.get_realm(realm_name=realm)
  1967. assert res["bruteForceProtected"] is False
  1968. def test_clear_bruteforce_attempts_for_user(
  1969. admin: KeycloakAdmin, oid_with_credentials: Tuple[KeycloakOpenID, str, str], realm: str
  1970. ):
  1971. """Test users.
  1972. :param admin: Keycloak Admin client
  1973. :type admin: KeycloakAdmin
  1974. :param oid_with_credentials: Keycloak OpenID client with pre-configured user credentials
  1975. :type oid_with_credentials: Tuple[KeycloakOpenID, str, str]
  1976. :param realm: Keycloak realm
  1977. :type realm: str
  1978. """
  1979. oid, username, password = oid_with_credentials
  1980. admin.realm_name = realm
  1981. # Turn on bruteforce protection
  1982. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": True})
  1983. res = admin.get_realm(realm_name=realm)
  1984. assert res["bruteForceProtected"] is True
  1985. # Test login user with wrong credentials
  1986. try:
  1987. oid.token(username=username, password="wrongpassword")
  1988. except KeycloakAuthenticationError:
  1989. pass
  1990. user_id = admin.get_user_id(username)
  1991. bruteforce_status = admin.get_bruteforce_detection_status(user_id)
  1992. assert bruteforce_status["numFailures"] == 1
  1993. res = admin.clear_bruteforce_attempts_for_user(user_id)
  1994. bruteforce_status = admin.get_bruteforce_detection_status(user_id)
  1995. assert bruteforce_status["numFailures"] == 0
  1996. # Cleanup
  1997. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": False})
  1998. res = admin.get_realm(realm_name=realm)
  1999. assert res["bruteForceProtected"] is False
  2000. def test_clear_bruteforce_attempts_for_all_users(
  2001. admin: KeycloakAdmin, oid_with_credentials: Tuple[KeycloakOpenID, str, str], realm: str
  2002. ):
  2003. """Test users.
  2004. :param admin: Keycloak Admin client
  2005. :type admin: KeycloakAdmin
  2006. :param oid_with_credentials: Keycloak OpenID client with pre-configured user credentials
  2007. :type oid_with_credentials: Tuple[KeycloakOpenID, str, str]
  2008. :param realm: Keycloak realm
  2009. :type realm: str
  2010. """
  2011. oid, username, password = oid_with_credentials
  2012. admin.realm_name = realm
  2013. # Turn on bruteforce protection
  2014. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": True})
  2015. res = admin.get_realm(realm_name=realm)
  2016. assert res["bruteForceProtected"] is True
  2017. # Test login user with wrong credentials
  2018. try:
  2019. oid.token(username=username, password="wrongpassword")
  2020. except KeycloakAuthenticationError:
  2021. pass
  2022. user_id = admin.get_user_id(username)
  2023. bruteforce_status = admin.get_bruteforce_detection_status(user_id)
  2024. assert bruteforce_status["numFailures"] == 1
  2025. res = admin.clear_all_bruteforce_attempts()
  2026. bruteforce_status = admin.get_bruteforce_detection_status(user_id)
  2027. assert bruteforce_status["numFailures"] == 0
  2028. # Cleanup
  2029. res = admin.update_realm(realm_name=realm, payload={"bruteForceProtected": False})
  2030. res = admin.get_realm(realm_name=realm)
  2031. assert res["bruteForceProtected"] is False
  2032. def test_default_realm_role_present(realm: str, admin: KeycloakAdmin) -> None:
  2033. """Test that the default realm role is present in a brand new realm.
  2034. :param realm: Realm name
  2035. :type realm: str
  2036. :param admin: Keycloak admin
  2037. :type admin: KeycloakAdmin
  2038. """
  2039. admin.realm_name = realm
  2040. assert f"default-roles-{realm}" in [x["name"] for x in admin.get_realm_roles()]
  2041. assert (
  2042. len([x["name"] for x in admin.get_realm_roles() if x["name"] == f"default-roles-{realm}"])
  2043. == 1
  2044. )
  2045. def test_get_default_realm_role_id(realm: str, admin: KeycloakAdmin) -> None:
  2046. """Test getter for the ID of the default realm role.
  2047. :param realm: Realm name
  2048. :type realm: str
  2049. :param admin: Keycloak admin
  2050. :type admin: KeycloakAdmin
  2051. """
  2052. admin.realm_name = realm
  2053. assert (
  2054. admin.get_default_realm_role_id()
  2055. == [x["id"] for x in admin.get_realm_roles() if x["name"] == f"default-roles-{realm}"][0]
  2056. )
  2057. def test_realm_default_roles(admin: KeycloakAdmin, realm: str) -> None:
  2058. """Test getting, adding and deleting default realm roles.
  2059. :param realm: Realm name
  2060. :type realm: str
  2061. :param admin: Keycloak admin
  2062. :type admin: KeycloakAdmin
  2063. """
  2064. admin.realm_name = realm
  2065. # Test listing all default realm roles
  2066. roles = admin.get_realm_default_roles()
  2067. assert len(roles) == 2
  2068. assert {x["name"] for x in roles} == {"offline_access", "uma_authorization"}
  2069. with pytest.raises(KeycloakGetError) as err:
  2070. admin.realm_name = "doesnotexist"
  2071. admin.get_realm_default_roles()
  2072. assert err.match('404: b\'{"error":"Realm not found."}\'')
  2073. admin.realm_name = realm
  2074. # Test removing a default realm role
  2075. res = admin.remove_realm_default_roles(payload=[roles[0]])
  2076. assert res == {}
  2077. assert roles[0] not in admin.get_realm_default_roles()
  2078. assert len(admin.get_realm_default_roles()) == 1
  2079. with pytest.raises(KeycloakDeleteError) as err:
  2080. admin.remove_realm_default_roles(payload=[{"id": "bad id"}])
  2081. assert err.match('404: b\'{"error":"Could not find composite role"}\'')
  2082. # Test adding a default realm role
  2083. res = admin.add_realm_default_roles(payload=[roles[0]])
  2084. assert res == {}
  2085. assert roles[0] in admin.get_realm_default_roles()
  2086. assert len(admin.get_realm_default_roles()) == 2
  2087. with pytest.raises(KeycloakPostError) as err:
  2088. admin.add_realm_default_roles(payload=[{"id": "bad id"}])
  2089. assert err.match('404: b\'{"error":"Could not find composite role"}\'')