@backstage-community/plugin-catalog-backend-module-keycloak 3.19.0 → 3.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/lib/read.cjs.js +8 -8
- package/dist/lib/read.cjs.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage-community/plugin-catalog-backend-module-keycloak
|
|
2
2
|
|
|
3
|
+
## 3.19.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 170f85d: Migrate to Jest 30
|
|
8
|
+
|
|
9
|
+
## 3.19.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- e8b7471: Fixes group fetching to default to the recursive subgroup strategy when the Keycloak server version cannot be determined from `serverInfo`. Previously, the version check could silently produce an unexpected result if `systemInfo.version` was absent; now the plugin defaults to `processGroupsRecursively` for all versions except those explicitly detected as 22 or lower, which continue to use the flat `traverseGroups` approach.
|
|
14
|
+
|
|
3
15
|
## 3.19.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/dist/lib/read.cjs.js
CHANGED
|
@@ -179,21 +179,21 @@ const readKeycloakRealm = async (client, config, logger, limit, taskInstanceId,
|
|
|
179
179
|
} catch (error) {
|
|
180
180
|
throw new Error(`Failed to retrieve Keycloak server information: ${error}`);
|
|
181
181
|
}
|
|
182
|
-
const
|
|
182
|
+
const isVersion22orLower = serverVersion <= 22;
|
|
183
183
|
let rawKGroups = [];
|
|
184
184
|
logger.debug(`Processing groups recursively`);
|
|
185
|
-
if (
|
|
185
|
+
if (isVersion22orLower) {
|
|
186
|
+
rawKGroups = topLevelKGroups.reduce(
|
|
187
|
+
(acc, g) => acc.concat(...traverseGroups(g)),
|
|
188
|
+
[]
|
|
189
|
+
);
|
|
190
|
+
} else {
|
|
186
191
|
rawKGroups = await processGroupsRecursively(
|
|
187
192
|
client,
|
|
188
193
|
config,
|
|
189
194
|
logger,
|
|
190
195
|
topLevelKGroups
|
|
191
196
|
);
|
|
192
|
-
} else {
|
|
193
|
-
rawKGroups = topLevelKGroups.reduce(
|
|
194
|
-
(acc, g) => acc.concat(...traverseGroups(g)),
|
|
195
|
-
[]
|
|
196
|
-
);
|
|
197
197
|
}
|
|
198
198
|
logger.debug(`Fetching group members for keycloak groups and list subgroups`);
|
|
199
199
|
const brief = config.briefRepresentation ?? constants.KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;
|
|
@@ -209,7 +209,7 @@ const readKeycloakRealm = async (client, config, logger, limit, taskInstanceId,
|
|
|
209
209
|
config,
|
|
210
210
|
options
|
|
211
211
|
);
|
|
212
|
-
if (
|
|
212
|
+
if (!isVersion22orLower) {
|
|
213
213
|
if (g.subGroupCount > 0) {
|
|
214
214
|
await authenticate.ensureTokenValid(client, config, logger);
|
|
215
215
|
g.subGroups = await client.groups.listSubGroups({
|
package/dist/lib/read.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.cjs.js","sources":["../../src/lib/read.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { GroupEntity, UserEntity } from '@backstage/catalog-model';\n\nimport type KeycloakAdminClient from '@keycloak/keycloak-admin-client';\nimport type GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';\nimport type UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation';\nimport type { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups';\nimport type { Users } from '@keycloak/keycloak-admin-client/lib/resources/users';\nimport { LimitFunction } from 'p-limit';\n\nimport { KeycloakProviderConfig } from './config';\nimport {\n KEYCLOAK_ENTITY_QUERY_SIZE,\n KEYCLOAK_ID_ANNOTATION,\n KEYCLOAK_REALM_ANNOTATION,\n KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT,\n} from './constants';\nimport {\n sanitizeUserNameTransformer,\n sanitizeGroupNameTransformer,\n} from './transformers';\nimport {\n GroupRepresentationWithParent,\n GroupRepresentationWithParentAndEntity,\n GroupTransformer,\n UserRepresentationWithEntity,\n UserTransformer,\n} from './types';\nimport { ensureTokenValid } from './authenticate';\nimport { Attributes, Counter } from '@opentelemetry/api';\n\nexport const parseGroup = async (\n keycloakGroup: GroupRepresentationWithParent,\n realm: string,\n groupTransformer?: GroupTransformer,\n): Promise<GroupEntity | undefined> => {\n const transformer = groupTransformer ?? sanitizeGroupNameTransformer;\n const entity: GroupEntity = {\n apiVersion: 'backstage.io/v1beta1',\n kind: 'Group',\n metadata: {\n name: keycloakGroup.name!,\n annotations: {\n [KEYCLOAK_ID_ANNOTATION]: keycloakGroup.id!,\n [KEYCLOAK_REALM_ANNOTATION]: realm,\n },\n },\n spec: {\n type: 'group',\n profile: {\n displayName: keycloakGroup.name!,\n },\n // children, parent and members are updated again after all group and user transformers applied.\n children: keycloakGroup.subGroups?.map(g => g.name!) ?? [],\n parent: keycloakGroup.parent,\n members: keycloakGroup.members,\n },\n };\n\n return await transformer(entity, keycloakGroup, realm);\n};\n\nexport const parseUser = async (\n user: UserRepresentation,\n realm: string,\n keycloakGroups: GroupRepresentationWithParentAndEntity[],\n groupIndex: Map<string, string[]>,\n userTransformer?: UserTransformer,\n): Promise<UserEntity | undefined> => {\n const transformer = userTransformer ?? sanitizeUserNameTransformer;\n const entity: UserEntity = {\n apiVersion: 'backstage.io/v1beta1',\n kind: 'User',\n metadata: {\n name: user.username!,\n annotations: {\n [KEYCLOAK_ID_ANNOTATION]: user.id!,\n [KEYCLOAK_REALM_ANNOTATION]: realm,\n },\n },\n spec: {\n profile: {\n email: user.email,\n ...(user.firstName || user.lastName\n ? {\n displayName: [user.firstName, user.lastName]\n .filter(Boolean)\n .join(' '),\n }\n : {}),\n },\n memberOf: groupIndex.get(user.username!) ?? [],\n },\n };\n\n return await transformer(entity, user, realm, keycloakGroups);\n};\n\nexport async function getEntities<T extends Users | Groups>(\n getEntitiesFn: () => Promise<T>,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n dataBatchFailureCounter: Counter<Attributes>,\n taskInstanceId: string,\n limit: LimitFunction,\n entityQuerySize: number = KEYCLOAK_ENTITY_QUERY_SIZE,\n): Promise<Awaited<ReturnType<T['find']>>> {\n const entitiesAPI = await getEntitiesFn();\n const rawEntityCount = await entitiesAPI.count({ realm: config.realm });\n const entityCount =\n typeof rawEntityCount === 'number' ? rawEntityCount : rawEntityCount.count;\n\n const pageCount = Math.ceil(entityCount / entityQuerySize);\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n // The next line acts like range in python\n const entityPromises = Array.from({ length: pageCount }, (_, i) =>\n limit(() =>\n getEntitiesFn().then(entities => {\n return entities\n .find({\n realm: config.realm,\n max: entityQuerySize,\n first: i * entityQuerySize,\n briefRepresentation: brief,\n })\n .then(ents => {\n logger.debug(\n `Importing keycloak entities batch with index ${i} from pages: ${pageCount}`,\n );\n return ents;\n })\n .catch(err => {\n dataBatchFailureCounter.add(1, { taskInstanceId: taskInstanceId });\n logger.warn(\n `Failed to retieve Keycloak entities for taskInstanceId: ${taskInstanceId}. Error: ${err}`,\n );\n return [];\n }) as ReturnType<T['find']>;\n }),\n ),\n );\n\n const entityResults = (await Promise.all(entityPromises)).flat() as Awaited<\n ReturnType<T['find']>\n >;\n\n return entityResults;\n}\n\nasync function getAllGroupMembers<T extends Groups>(\n groupsAPI: () => Promise<T>,\n groupId: string,\n config: KeycloakProviderConfig,\n options?: { userQuerySize?: number },\n): Promise<string[]> {\n const querySize = options?.userQuerySize || 100;\n\n let allMembers: string[] = [];\n let page = 0;\n let totalMembers = 0;\n\n do {\n const groups = await groupsAPI();\n const members = await groups.listMembers({\n id: groupId,\n max: querySize,\n realm: config.realm,\n first: page * querySize,\n });\n\n if (members.length > 0) {\n allMembers = allMembers.concat(members.map(m => m.username!));\n totalMembers = members.length; // Get the number of members retrieved\n } else {\n totalMembers = 0; // No members retrieved\n }\n\n page++;\n } while (totalMembers > 0);\n\n return allMembers;\n}\n\nexport async function processGroupsRecursively(\n kcAdminClient: KeycloakAdminClient,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n topLevelGroups: GroupRepresentationWithParent[],\n) {\n const allGroups: GroupRepresentationWithParent[] = [];\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n for (const group of topLevelGroups) {\n allGroups.push(group);\n\n if (group.subGroupCount! > 0) {\n await ensureTokenValid(kcAdminClient, config, logger);\n const subgroups = await kcAdminClient.groups.listSubGroups({\n parentId: group.id!,\n first: 0,\n max: group.subGroupCount,\n briefRepresentation: brief,\n realm: config.realm,\n });\n const subGroupResults = await processGroupsRecursively(\n kcAdminClient,\n config,\n logger,\n subgroups,\n );\n allGroups.push(...subGroupResults);\n }\n }\n\n return allGroups;\n}\n\nexport function* traverseGroups(\n group: GroupRepresentation,\n): IterableIterator<GroupRepresentationWithParent> {\n yield group;\n for (const g of group.subGroups ?? []) {\n (g as GroupRepresentationWithParent).parent = group.name!;\n yield* traverseGroups(g);\n }\n}\n\nexport const readKeycloakRealm = async (\n client: KeycloakAdminClient,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n limit: LimitFunction,\n taskInstanceId: string,\n dataBatchFailureCounter: Counter<Attributes>,\n options?: {\n userQuerySize?: number;\n groupQuerySize?: number;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n },\n): Promise<{\n users: UserEntity[];\n groups: GroupEntity[];\n}> => {\n const kUsers = await getEntities(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.users;\n },\n config,\n logger,\n dataBatchFailureCounter,\n taskInstanceId,\n limit,\n options?.userQuerySize,\n );\n logger.debug(`Fetched ${kUsers.length} users from Keycloak`);\n\n const topLevelKGroups = (await getEntities(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.groups;\n },\n config,\n logger,\n dataBatchFailureCounter,\n taskInstanceId,\n limit,\n options?.groupQuerySize,\n )) as GroupRepresentationWithParent[];\n logger.debug(`Fetched ${topLevelKGroups.length} groups from Keycloak`);\n\n let serverVersion: number;\n\n try {\n await ensureTokenValid(client, config, logger);\n const serverInfo = await client.serverInfo.find();\n serverVersion = parseInt(\n serverInfo.systemInfo?.version?.slice(0, 2) || '',\n 10,\n );\n } catch (error) {\n throw new Error(`Failed to retrieve Keycloak server information: ${error}`);\n }\n\n const isVersion23orHigher = serverVersion >= 23;\n\n let rawKGroups: GroupRepresentationWithParent[] = [];\n\n logger.debug(`Processing groups recursively`);\n if (isVersion23orHigher) {\n rawKGroups = await processGroupsRecursively(\n client,\n config,\n logger,\n topLevelKGroups,\n );\n } else {\n rawKGroups = topLevelKGroups.reduce(\n (acc, g) => acc.concat(...traverseGroups(g)),\n [] as GroupRepresentationWithParent[],\n );\n }\n\n logger.debug(`Fetching group members for keycloak groups and list subgroups`);\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n const kGroups = await Promise.all(\n rawKGroups.map(g =>\n limit(async () => {\n g.members = await getAllGroupMembers(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.groups as Groups;\n },\n g.id!,\n config,\n options,\n );\n\n if (isVersion23orHigher) {\n if (g.subGroupCount! > 0) {\n await ensureTokenValid(client, config, logger);\n g.subGroups = await client.groups.listSubGroups({\n parentId: g.id!,\n first: 0,\n max: g.subGroupCount,\n briefRepresentation: brief,\n realm: config.realm,\n });\n }\n if (g.parentId) {\n await ensureTokenValid(client, config, logger);\n const groupParent = await client.groups.findOne({\n id: g.parentId,\n realm: config.realm,\n });\n g.parent = groupParent?.name;\n }\n }\n\n return g;\n }),\n ),\n );\n\n logger.debug(`Parsing groups`);\n const parsedGroups = await Promise.all(\n kGroups.map(async g => {\n // it is possible if fetch request failed\n if (!g) {\n return null;\n }\n const entity = await parseGroup(\n g,\n config.realm,\n options?.groupTransformer,\n );\n if (entity) {\n return { ...g, entity } as GroupRepresentationWithParentAndEntity;\n }\n return null;\n }),\n );\n const filteredParsedGroups = parsedGroups.filter(\n (group): group is GroupRepresentationWithParentAndEntity => group !== null,\n );\n\n const groupIndex = new Map<string, string[]>();\n filteredParsedGroups.forEach(group => {\n if (group.members) {\n group.members.forEach(member => {\n if (!groupIndex.has(member)) {\n groupIndex.set(member, []);\n }\n groupIndex.get(member)?.push(group.entity.metadata.name);\n });\n }\n });\n\n logger.debug('Parsing users');\n const parsedUsers = await Promise.all(\n kUsers.map(async u => {\n // it is possible if fetch request failed\n if (!u) {\n return null;\n }\n const entity = await parseUser(\n u,\n config.realm,\n filteredParsedGroups,\n groupIndex,\n options?.userTransformer,\n );\n if (entity) {\n return { ...u, entity } as UserRepresentationWithEntity;\n }\n return null;\n }),\n );\n const filteredParsedUsers = parsedUsers.filter(\n (user): user is UserRepresentationWithEntity => user !== null,\n );\n\n logger.debug(`Set up group members and children information`);\n\n const userMap = new Map(\n filteredParsedUsers.map(user => [user.username, user.entity.metadata.name]),\n );\n\n const groupMap = new Map(\n filteredParsedGroups.map(group => [group.name, group.entity.metadata.name]),\n );\n\n const groups = filteredParsedGroups.map(g => {\n const entity = g.entity;\n entity.spec.members =\n g.entity.spec.members?.flatMap(m => userMap.get(m) ?? []) ?? [];\n entity.spec.children =\n g.entity.spec.children?.flatMap(c => groupMap.get(c) ?? []) ?? [];\n entity.spec.parent = groupMap.get(entity.spec.parent);\n return entity;\n });\n\n logger.info(\n `Prepared to ingest ${parsedUsers.length} users and ${groups.length} groups into the catalog from Keycloak`,\n );\n\n return { users: filteredParsedUsers.map(u => u.entity), groups };\n};\n"],"names":["sanitizeGroupNameTransformer","KEYCLOAK_ID_ANNOTATION","KEYCLOAK_REALM_ANNOTATION","sanitizeUserNameTransformer","KEYCLOAK_ENTITY_QUERY_SIZE","KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT","ensureTokenValid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"read.cjs.js","sources":["../../src/lib/read.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { LoggerService } from '@backstage/backend-plugin-api';\nimport type { GroupEntity, UserEntity } from '@backstage/catalog-model';\n\nimport type KeycloakAdminClient from '@keycloak/keycloak-admin-client';\nimport type GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';\nimport type UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation';\nimport type { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups';\nimport type { Users } from '@keycloak/keycloak-admin-client/lib/resources/users';\nimport { LimitFunction } from 'p-limit';\n\nimport { KeycloakProviderConfig } from './config';\nimport {\n KEYCLOAK_ENTITY_QUERY_SIZE,\n KEYCLOAK_ID_ANNOTATION,\n KEYCLOAK_REALM_ANNOTATION,\n KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT,\n} from './constants';\nimport {\n sanitizeUserNameTransformer,\n sanitizeGroupNameTransformer,\n} from './transformers';\nimport {\n GroupRepresentationWithParent,\n GroupRepresentationWithParentAndEntity,\n GroupTransformer,\n UserRepresentationWithEntity,\n UserTransformer,\n} from './types';\nimport { ensureTokenValid } from './authenticate';\nimport { Attributes, Counter } from '@opentelemetry/api';\n\nexport const parseGroup = async (\n keycloakGroup: GroupRepresentationWithParent,\n realm: string,\n groupTransformer?: GroupTransformer,\n): Promise<GroupEntity | undefined> => {\n const transformer = groupTransformer ?? sanitizeGroupNameTransformer;\n const entity: GroupEntity = {\n apiVersion: 'backstage.io/v1beta1',\n kind: 'Group',\n metadata: {\n name: keycloakGroup.name!,\n annotations: {\n [KEYCLOAK_ID_ANNOTATION]: keycloakGroup.id!,\n [KEYCLOAK_REALM_ANNOTATION]: realm,\n },\n },\n spec: {\n type: 'group',\n profile: {\n displayName: keycloakGroup.name!,\n },\n // children, parent and members are updated again after all group and user transformers applied.\n children: keycloakGroup.subGroups?.map(g => g.name!) ?? [],\n parent: keycloakGroup.parent,\n members: keycloakGroup.members,\n },\n };\n\n return await transformer(entity, keycloakGroup, realm);\n};\n\nexport const parseUser = async (\n user: UserRepresentation,\n realm: string,\n keycloakGroups: GroupRepresentationWithParentAndEntity[],\n groupIndex: Map<string, string[]>,\n userTransformer?: UserTransformer,\n): Promise<UserEntity | undefined> => {\n const transformer = userTransformer ?? sanitizeUserNameTransformer;\n const entity: UserEntity = {\n apiVersion: 'backstage.io/v1beta1',\n kind: 'User',\n metadata: {\n name: user.username!,\n annotations: {\n [KEYCLOAK_ID_ANNOTATION]: user.id!,\n [KEYCLOAK_REALM_ANNOTATION]: realm,\n },\n },\n spec: {\n profile: {\n email: user.email,\n ...(user.firstName || user.lastName\n ? {\n displayName: [user.firstName, user.lastName]\n .filter(Boolean)\n .join(' '),\n }\n : {}),\n },\n memberOf: groupIndex.get(user.username!) ?? [],\n },\n };\n\n return await transformer(entity, user, realm, keycloakGroups);\n};\n\nexport async function getEntities<T extends Users | Groups>(\n getEntitiesFn: () => Promise<T>,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n dataBatchFailureCounter: Counter<Attributes>,\n taskInstanceId: string,\n limit: LimitFunction,\n entityQuerySize: number = KEYCLOAK_ENTITY_QUERY_SIZE,\n): Promise<Awaited<ReturnType<T['find']>>> {\n const entitiesAPI = await getEntitiesFn();\n const rawEntityCount = await entitiesAPI.count({ realm: config.realm });\n const entityCount =\n typeof rawEntityCount === 'number' ? rawEntityCount : rawEntityCount.count;\n\n const pageCount = Math.ceil(entityCount / entityQuerySize);\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n // The next line acts like range in python\n const entityPromises = Array.from({ length: pageCount }, (_, i) =>\n limit(() =>\n getEntitiesFn().then(entities => {\n return entities\n .find({\n realm: config.realm,\n max: entityQuerySize,\n first: i * entityQuerySize,\n briefRepresentation: brief,\n })\n .then(ents => {\n logger.debug(\n `Importing keycloak entities batch with index ${i} from pages: ${pageCount}`,\n );\n return ents;\n })\n .catch(err => {\n dataBatchFailureCounter.add(1, { taskInstanceId: taskInstanceId });\n logger.warn(\n `Failed to retieve Keycloak entities for taskInstanceId: ${taskInstanceId}. Error: ${err}`,\n );\n return [];\n }) as ReturnType<T['find']>;\n }),\n ),\n );\n\n const entityResults = (await Promise.all(entityPromises)).flat() as Awaited<\n ReturnType<T['find']>\n >;\n\n return entityResults;\n}\n\nasync function getAllGroupMembers<T extends Groups>(\n groupsAPI: () => Promise<T>,\n groupId: string,\n config: KeycloakProviderConfig,\n options?: { userQuerySize?: number },\n): Promise<string[]> {\n const querySize = options?.userQuerySize || 100;\n\n let allMembers: string[] = [];\n let page = 0;\n let totalMembers = 0;\n\n do {\n const groups = await groupsAPI();\n const members = await groups.listMembers({\n id: groupId,\n max: querySize,\n realm: config.realm,\n first: page * querySize,\n });\n\n if (members.length > 0) {\n allMembers = allMembers.concat(members.map(m => m.username!));\n totalMembers = members.length; // Get the number of members retrieved\n } else {\n totalMembers = 0; // No members retrieved\n }\n\n page++;\n } while (totalMembers > 0);\n\n return allMembers;\n}\n\nexport async function processGroupsRecursively(\n kcAdminClient: KeycloakAdminClient,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n topLevelGroups: GroupRepresentationWithParent[],\n) {\n const allGroups: GroupRepresentationWithParent[] = [];\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n for (const group of topLevelGroups) {\n allGroups.push(group);\n\n if (group.subGroupCount! > 0) {\n await ensureTokenValid(kcAdminClient, config, logger);\n const subgroups = await kcAdminClient.groups.listSubGroups({\n parentId: group.id!,\n first: 0,\n max: group.subGroupCount,\n briefRepresentation: brief,\n realm: config.realm,\n });\n const subGroupResults = await processGroupsRecursively(\n kcAdminClient,\n config,\n logger,\n subgroups,\n );\n allGroups.push(...subGroupResults);\n }\n }\n\n return allGroups;\n}\n\nexport function* traverseGroups(\n group: GroupRepresentation,\n): IterableIterator<GroupRepresentationWithParent> {\n yield group;\n for (const g of group.subGroups ?? []) {\n (g as GroupRepresentationWithParent).parent = group.name!;\n yield* traverseGroups(g);\n }\n}\n\nexport const readKeycloakRealm = async (\n client: KeycloakAdminClient,\n config: KeycloakProviderConfig,\n logger: LoggerService,\n limit: LimitFunction,\n taskInstanceId: string,\n dataBatchFailureCounter: Counter<Attributes>,\n options?: {\n userQuerySize?: number;\n groupQuerySize?: number;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n },\n): Promise<{\n users: UserEntity[];\n groups: GroupEntity[];\n}> => {\n const kUsers = await getEntities(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.users;\n },\n config,\n logger,\n dataBatchFailureCounter,\n taskInstanceId,\n limit,\n options?.userQuerySize,\n );\n logger.debug(`Fetched ${kUsers.length} users from Keycloak`);\n\n const topLevelKGroups = (await getEntities(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.groups;\n },\n config,\n logger,\n dataBatchFailureCounter,\n taskInstanceId,\n limit,\n options?.groupQuerySize,\n )) as GroupRepresentationWithParent[];\n logger.debug(`Fetched ${topLevelKGroups.length} groups from Keycloak`);\n\n let serverVersion: number;\n\n try {\n await ensureTokenValid(client, config, logger);\n const serverInfo = await client.serverInfo.find();\n\n serverVersion = parseInt(\n serverInfo.systemInfo?.version?.slice(0, 2) || '',\n 10,\n );\n } catch (error) {\n throw new Error(`Failed to retrieve Keycloak server information: ${error}`);\n }\n\n const isVersion22orLower = serverVersion <= 22;\n\n let rawKGroups: GroupRepresentationWithParent[] = [];\n\n logger.debug(`Processing groups recursively`);\n if (isVersion22orLower) {\n rawKGroups = topLevelKGroups.reduce(\n (acc, g) => acc.concat(...traverseGroups(g)),\n [] as GroupRepresentationWithParent[],\n );\n } else {\n rawKGroups = await processGroupsRecursively(\n client,\n config,\n logger,\n topLevelKGroups,\n );\n }\n\n logger.debug(`Fetching group members for keycloak groups and list subgroups`);\n const brief =\n config.briefRepresentation ?? KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT;\n\n const kGroups = await Promise.all(\n rawKGroups.map(g =>\n limit(async () => {\n g.members = await getAllGroupMembers(\n async () => {\n await ensureTokenValid(client, config, logger);\n return client.groups as Groups;\n },\n g.id!,\n config,\n options,\n );\n\n if (!isVersion22orLower) {\n if (g.subGroupCount! > 0) {\n await ensureTokenValid(client, config, logger);\n g.subGroups = await client.groups.listSubGroups({\n parentId: g.id!,\n first: 0,\n max: g.subGroupCount,\n briefRepresentation: brief,\n realm: config.realm,\n });\n }\n if (g.parentId) {\n await ensureTokenValid(client, config, logger);\n const groupParent = await client.groups.findOne({\n id: g.parentId,\n realm: config.realm,\n });\n g.parent = groupParent?.name;\n }\n }\n\n return g;\n }),\n ),\n );\n\n logger.debug(`Parsing groups`);\n const parsedGroups = await Promise.all(\n kGroups.map(async g => {\n // it is possible if fetch request failed\n if (!g) {\n return null;\n }\n const entity = await parseGroup(\n g,\n config.realm,\n options?.groupTransformer,\n );\n if (entity) {\n return { ...g, entity } as GroupRepresentationWithParentAndEntity;\n }\n return null;\n }),\n );\n const filteredParsedGroups = parsedGroups.filter(\n (group): group is GroupRepresentationWithParentAndEntity => group !== null,\n );\n\n const groupIndex = new Map<string, string[]>();\n filteredParsedGroups.forEach(group => {\n if (group.members) {\n group.members.forEach(member => {\n if (!groupIndex.has(member)) {\n groupIndex.set(member, []);\n }\n groupIndex.get(member)?.push(group.entity.metadata.name);\n });\n }\n });\n\n logger.debug('Parsing users');\n const parsedUsers = await Promise.all(\n kUsers.map(async u => {\n // it is possible if fetch request failed\n if (!u) {\n return null;\n }\n const entity = await parseUser(\n u,\n config.realm,\n filteredParsedGroups,\n groupIndex,\n options?.userTransformer,\n );\n if (entity) {\n return { ...u, entity } as UserRepresentationWithEntity;\n }\n return null;\n }),\n );\n const filteredParsedUsers = parsedUsers.filter(\n (user): user is UserRepresentationWithEntity => user !== null,\n );\n\n logger.debug(`Set up group members and children information`);\n\n const userMap = new Map(\n filteredParsedUsers.map(user => [user.username, user.entity.metadata.name]),\n );\n\n const groupMap = new Map(\n filteredParsedGroups.map(group => [group.name, group.entity.metadata.name]),\n );\n\n const groups = filteredParsedGroups.map(g => {\n const entity = g.entity;\n entity.spec.members =\n g.entity.spec.members?.flatMap(m => userMap.get(m) ?? []) ?? [];\n entity.spec.children =\n g.entity.spec.children?.flatMap(c => groupMap.get(c) ?? []) ?? [];\n entity.spec.parent = groupMap.get(entity.spec.parent);\n return entity;\n });\n\n logger.info(\n `Prepared to ingest ${parsedUsers.length} users and ${groups.length} groups into the catalog from Keycloak`,\n );\n\n return { users: filteredParsedUsers.map(u => u.entity), groups };\n};\n"],"names":["sanitizeGroupNameTransformer","KEYCLOAK_ID_ANNOTATION","KEYCLOAK_REALM_ANNOTATION","sanitizeUserNameTransformer","KEYCLOAK_ENTITY_QUERY_SIZE","KEYCLOAK_BRIEF_REPRESENTATION_DEFAULT","ensureTokenValid"],"mappings":"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"}
|
package/package.json
CHANGED