Keycloak - 将所有用户映射到角色
Keycloak - Get all Users mapped to roles
我知道 keycloak 暴露在下面 api,
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>2.0.0.Final</version>
</dependency>
具有完整的文档here。我在这里找不到所需的 api 来获取所有映射到特定角色的用户。
问题陈述 - 我需要从 keycloak 服务器中选择所有具有特定角色的用户。我需要向所有角色映射到他们的用户发送电子邮件。
有一个未完成的 feature request 通过 API 请求此功能。
同时,如果您的需求是一次性的,您可以通过查询连接 KEYCLOAK_ROLE 到 USER_ROLE_MAPPING 到 USER_ENTITY[= 的数据库来获取用户名(或电子邮件地址) 12=]
类似于:
SELECT username
FROM keycloak_role kr
JOIN user_role_mapping rm ON kr.id = rm.role_id
JOIN user_entity ue ON rm.user_id = ue.id
WHERE kr.name = 'your_role_name';
根据 documentation 看来是这样 API:
GET /{realm}/clients/{id}/roles/{role-name}/users
它在那里有一段时间了。然而,在这个旧版本中,不可能通过这种方式获得超过 100 个用户。稍后修复并添加了分页选项。
这是另一个有趣的查询,它还会显示其他有用的字段。
SELECT kr_role.REALM_ID 'Realm', cl.CLIENT_ID 'Realm Client',
kr_role.NAME 'Role Name',
kr_role.DESCRIPTION 'Role Description',
user_ent.USERNAME 'Domain ID', user_ent.EMAIL 'Email'
FROM keycloak_role kr_role, user_role_mapping role_map,
user_entity user_ent, client cl
WHERE role_map.USER_ID = user_ent.ID
AND kr_role.ID = role_map.ROLE_ID
AND kr_role.CLIENT = cl.ID
AND cl.REALM_ID = '<realm_name>'
AND cl.CLIENT_ID = '<client_name>'
ORDER BY 1, 2, 3;
更新后的休息端点现在应该可以做到这一点。
Set<UserRepresentation> usersOfRole = realmResource.roles().get(roleName).getRoleUserMembers();
SELECT username,
kr.NAME,
kr.REALM_ID
FROM KEYCLOAK_ROLE kr
JOIN USER_ROLE_MAPPING rm ON kr.id = rm.role_id
JOIN USER_ENTITY ue ON rm.user_id = ue.id
ORDER BY USERNAME,
NAME,
REALM_ID;
如果有人仍在搜索 Postgres 查询以在 keycloak 数据库中查找有关 users/roles/groups 的信息,我最近想到了这个。
它使用两个 CTE 来明确组和角色(对于组中的组递归,因为它们可以嵌套在任意深度,并使用它们的父级获取复合角色)和一个简单的 UNION 用于组和直接分配。
请注意 WHERE 子句,您可以在其中限制领域和不同方面。您可以搜索
- 来自特定用户的所有角色(仅匹配
username
)
- 分配了特定角色的所有用户(匹配
role_name
)
- 来自特定组的所有内容(我有时在投影中没有
username
列的情况下使用它只是为了查看组具有什么角色。请注意组列中的前缀)
-- flat out GROUPS in GROUPS
WITH RECURSIVE groups AS (
SELECT
g.id,
g.id AS parent_group,
g.name,
g.name AS parent_name,
g.realm_id,
1 AS iter
FROM
keycloak_group g
UNION
SELECT
groups.id,
parents.parent_group,
groups.name,
parents.name,
groups.realm_id,
groups.iter + 1
FROM
groups
INNER JOIN keycloak_group parents ON groups.parent_group = parents.id
),
-- Collect roles and composite roles
roles AS (
SELECT
r.id,
r.name AS role_name,
null AS base_role,
c.client_id
FROM
keycloak_role r
LEFT JOIN client c ON r.client = c.id
UNION
SELECT
r.id,
r2.name,
r.name,
c.client_id
FROM
keycloak_role r
JOIN composite_role cr ON r.id = cr.composite
JOIN keycloak_role r2 ON r2.id = cr.child_role
LEFT JOIN client c ON r.client = c.id
)
SELECT DISTINCT
username,
role_name,
base_role, -- for composite roles
client_id,
source,
realm_name
FROM
(
-- Roles from Groups
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'group ' || g.name AS source,
realm.name AS realm_name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_group_membership ugm ON ue.id = ugm.user_id
JOIN groups g ON g.id = ugm.group_id
JOIN group_role_mapping grm ON g.parent_group = grm.group_id
JOIN roles roles ON roles.id = grm.role_id
UNION
-- direct role assignments on User
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'direct',
realm.name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_role_mapping urm ON ue.id = urm.user_id
JOIN roles roles ON roles.id = urm.role_id
) AS a
WHERE
realm_name = 'realm_name'
AND (
-- username = 'username'
role_name IN ('roleName')
-- source = 'group GROUPNAME'
)
ORDER BY
username,
role_name
;
此查询适用于 keycloak 9 到 16.1.1(我从 docker hub 获得的最后一个 jboss/keycloak 版本)。
我知道 keycloak 暴露在下面 api,
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>2.0.0.Final</version>
</dependency>
具有完整的文档here。我在这里找不到所需的 api 来获取所有映射到特定角色的用户。
问题陈述 - 我需要从 keycloak 服务器中选择所有具有特定角色的用户。我需要向所有角色映射到他们的用户发送电子邮件。
有一个未完成的 feature request 通过 API 请求此功能。
同时,如果您的需求是一次性的,您可以通过查询连接 KEYCLOAK_ROLE 到 USER_ROLE_MAPPING 到 USER_ENTITY[= 的数据库来获取用户名(或电子邮件地址) 12=]
类似于:
SELECT username
FROM keycloak_role kr
JOIN user_role_mapping rm ON kr.id = rm.role_id
JOIN user_entity ue ON rm.user_id = ue.id
WHERE kr.name = 'your_role_name';
根据 documentation 看来是这样 API:
GET /{realm}/clients/{id}/roles/{role-name}/users
它在那里有一段时间了。然而,在这个旧版本中,不可能通过这种方式获得超过 100 个用户。稍后修复并添加了分页选项。
这是另一个有趣的查询,它还会显示其他有用的字段。
SELECT kr_role.REALM_ID 'Realm', cl.CLIENT_ID 'Realm Client',
kr_role.NAME 'Role Name',
kr_role.DESCRIPTION 'Role Description',
user_ent.USERNAME 'Domain ID', user_ent.EMAIL 'Email'
FROM keycloak_role kr_role, user_role_mapping role_map,
user_entity user_ent, client cl
WHERE role_map.USER_ID = user_ent.ID
AND kr_role.ID = role_map.ROLE_ID
AND kr_role.CLIENT = cl.ID
AND cl.REALM_ID = '<realm_name>'
AND cl.CLIENT_ID = '<client_name>'
ORDER BY 1, 2, 3;
更新后的休息端点现在应该可以做到这一点。
Set<UserRepresentation> usersOfRole = realmResource.roles().get(roleName).getRoleUserMembers();
SELECT username,
kr.NAME,
kr.REALM_ID
FROM KEYCLOAK_ROLE kr
JOIN USER_ROLE_MAPPING rm ON kr.id = rm.role_id
JOIN USER_ENTITY ue ON rm.user_id = ue.id
ORDER BY USERNAME,
NAME,
REALM_ID;
如果有人仍在搜索 Postgres 查询以在 keycloak 数据库中查找有关 users/roles/groups 的信息,我最近想到了这个。
它使用两个 CTE 来明确组和角色(对于组中的组递归,因为它们可以嵌套在任意深度,并使用它们的父级获取复合角色)和一个简单的 UNION 用于组和直接分配。
请注意 WHERE 子句,您可以在其中限制领域和不同方面。您可以搜索
- 来自特定用户的所有角色(仅匹配
username
) - 分配了特定角色的所有用户(匹配
role_name
) - 来自特定组的所有内容(我有时在投影中没有
username
列的情况下使用它只是为了查看组具有什么角色。请注意组列中的前缀)
-- flat out GROUPS in GROUPS
WITH RECURSIVE groups AS (
SELECT
g.id,
g.id AS parent_group,
g.name,
g.name AS parent_name,
g.realm_id,
1 AS iter
FROM
keycloak_group g
UNION
SELECT
groups.id,
parents.parent_group,
groups.name,
parents.name,
groups.realm_id,
groups.iter + 1
FROM
groups
INNER JOIN keycloak_group parents ON groups.parent_group = parents.id
),
-- Collect roles and composite roles
roles AS (
SELECT
r.id,
r.name AS role_name,
null AS base_role,
c.client_id
FROM
keycloak_role r
LEFT JOIN client c ON r.client = c.id
UNION
SELECT
r.id,
r2.name,
r.name,
c.client_id
FROM
keycloak_role r
JOIN composite_role cr ON r.id = cr.composite
JOIN keycloak_role r2 ON r2.id = cr.child_role
LEFT JOIN client c ON r.client = c.id
)
SELECT DISTINCT
username,
role_name,
base_role, -- for composite roles
client_id,
source,
realm_name
FROM
(
-- Roles from Groups
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'group ' || g.name AS source,
realm.name AS realm_name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_group_membership ugm ON ue.id = ugm.user_id
JOIN groups g ON g.id = ugm.group_id
JOIN group_role_mapping grm ON g.parent_group = grm.group_id
JOIN roles roles ON roles.id = grm.role_id
UNION
-- direct role assignments on User
SELECT
ue.username,
roles.role_name,
roles.base_role,
roles.client_id,
ue.realm_id,
'direct',
realm.name
FROM
user_entity ue
JOIN realm ON ue.realm_id = realm.id
JOIN user_role_mapping urm ON ue.id = urm.user_id
JOIN roles roles ON roles.id = urm.role_id
) AS a
WHERE
realm_name = 'realm_name'
AND (
-- username = 'username'
role_name IN ('roleName')
-- source = 'group GROUPNAME'
)
ORDER BY
username,
role_name
;
此查询适用于 keycloak 9 到 16.1.1(我从 docker hub 获得的最后一个 jboss/keycloak 版本)。