Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/keycloak/keycloak_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2216,6 +2216,33 @@ def get_client_authz_settings(self, client_id: str) -> dict:
)
return raise_error_from_response(data_raw, KeycloakGetError)

def import_client_authz_config(self, client_id: str, payload: dict) -> dict:
"""
Import client authorization configuration.

ResourceServerRepresentation
https://www.keycloak.org/docs-api/latest/rest-api/index.html#ResourceServerRepresentation

:param client_id: id in ClientRepresentation
https://www.keycloak.org/docs-api/24.0.2/rest-api/index.html#_clientrepresentation
:type client_id: str
:param payload: ResourceServerRepresentation
:type payload: dict

:return: None
"""
params_path = {"realm-name": self.connection.realm_name, "id": client_id}
data_raw = self.connection.raw_post(
urls_patterns.URL_ADMIN_CLIENT_AUTHZ_IMPORT.format(**params_path),
data=json.dumps(payload),
)

return raise_error_from_response(
data_raw,
KeycloakPostError,
expected_codes=[HTTP_NO_CONTENT],
)

def create_client_authz_resource(
self,
client_id: str,
Expand Down Expand Up @@ -7527,6 +7554,33 @@ async def a_get_client_authz_settings(self, client_id: str) -> dict:
)
return raise_error_from_response(data_raw, KeycloakGetError)

async def a_import_client_authz_config(self, client_id: str, payload: dict) -> dict:
"""
Import client authorization configuration asynchronously.

ResourceServerRepresentation
https://www.keycloak.org/docs-api/latest/rest-api/index.html#ResourceServerRepresentation

:param client_id: id in ClientRepresentation
https://www.keycloak.org/docs-api/24.0.2/rest-api/index.html#_clientrepresentation
:type client_id: str
:param payload: ResourceServerRepresentation
:type payload: dict

:return: None
"""
params_path = {"realm-name": self.connection.realm_name, "id": client_id}
data_raw = await self.connection.a_raw_post(
urls_patterns.URL_ADMIN_CLIENT_AUTHZ_IMPORT.format(**params_path),
data=json.dumps(payload),
)

return raise_error_from_response(
data_raw,
KeycloakPostError,
expected_codes=[HTTP_NO_CONTENT],
)

async def a_create_client_authz_resource(
self,
client_id: str,
Expand Down
1 change: 1 addition & 0 deletions src/keycloak/urls_patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@

URL_ADMIN_CLIENT_AUTHZ = URL_ADMIN_CLIENT + "/authz/resource-server"
URL_ADMIN_CLIENT_AUTHZ_SETTINGS = URL_ADMIN_CLIENT_AUTHZ + "/settings"
URL_ADMIN_CLIENT_AUTHZ_IMPORT = URL_ADMIN_CLIENT_AUTHZ + "/import"
URL_ADMIN_CLIENT_AUTHZ_RESOURCE = URL_ADMIN_CLIENT_AUTHZ + "/resource/{resource-id}"
URL_ADMIN_CLIENT_AUTHZ_RESOURCES = URL_ADMIN_CLIENT_AUTHZ + "/resource"
URL_ADMIN_CLIENT_AUTHZ_SCOPES = URL_ADMIN_CLIENT_AUTHZ + "/scope"
Expand Down
70 changes: 70 additions & 0 deletions tests/test_keycloak_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,41 @@ def test_clients(admin: KeycloakAdmin, realm: str) -> None:
UNKOWN_ERROR_REGEX,
)

# Test import authz
authz_config = admin.get_client_authz_settings(client_id=auth_client_id)

authz_config["resources"] = [{"name": "test-import-resource"}]
authz_config["policies"] = [
{
"name": "test-import-policy",
"type": "time",
"config": {"hourEnd": "18", "hour": "9"},
}
]
admin.import_client_authz_config(client_id=auth_client_id, payload=authz_config)
exported = admin.get_client_authz_settings(client_id=auth_client_id)
assert (
len(
[
resource
for resource in exported["resources"]
if resource["name"] == "test-import-resource"
]
)
== 1
)

assert (
len(
[
resource
for resource in exported["policies"]
if resource["name"] == "test-import-policy"
]
)
== 1
)

# Test delete client
res = admin.delete_client(client_id=auth_client_id)
assert res == {}, res
Expand Down Expand Up @@ -5042,6 +5077,41 @@ async def test_a_clients(admin: KeycloakAdmin, realm: str) -> None:
UNKOWN_ERROR_REGEX,
)

# Test async import authz
authz_config = await admin.a_get_client_authz_settings(client_id=auth_client_id)

authz_config["resources"] = [{"name": "test-import-resource"}]
authz_config["policies"] = [
{
"name": "test-import-policy",
"type": "time",
"config": {"hourEnd": "18", "hour": "9"},
}
]
await admin.a_import_client_authz_config(client_id=auth_client_id, payload=authz_config)
exported = await admin.a_get_client_authz_settings(client_id=auth_client_id)
assert (
len(
[
resource
for resource in exported["resources"]
if resource["name"] == "test-import-resource"
]
)
== 1
)

assert (
len(
[
resource
for resource in exported["policies"]
if resource["name"] == "test-import-policy"
]
)
== 1
)

# Test delete client
res = await admin.a_delete_client(client_id=auth_client_id)
assert res == {}, res
Expand Down