-
Bug
-
Resolution: Unresolved
-
Blocker
-
None
[2627201995] Upstream Reporter: JohannesWill
Upstream issue status: Open
Upstream description:
Describe the bug
I have setup the Keycloak backend plugin by following the steps given on below this link - https://janus-idp.io/plugins/keycloak/ .
Syncing the users and Groups will overload our Keycloak instance by doing many parrallel requests
Expected Behavior
- All users and groups from keyclock realm should be synced
- The Keycloak server should not experience a DoS (Denial of Service).
What are the steps to reproduce this bug?
- Keycloak with many users and groups (in my case ~2500 users and 850 groups)
- Configure the Keycloak plugin for new backup configuration (using steps from https://janus-idp.io/plugins/keycloak/)
Versions of software used and environment @janus-idp/backstage-plugin-keycloak-backend": "^2.0.8",
Backstage - 1.30.4 (create-app@0.5.18)
Temporary Workaround: During investigation of that problem I used patch-package to patch @janus-idp/backstage-plugin-keycloak-backend@2.0.8 for the project I'm working on. With that pacht, where I serialized the calls to Keycloak, the problem is not reproduceable anymore.
Here is the diff that solved my problem:
Unable to find source-code formatter for language: diff. Available languages are: actionscript, ada, applescript, bash, c, c#, c++, cpp, css, erlang, go, groovy, haskell, html, java, javascript, js, json, lua, none, nyan, objc, perl, php, python, r, rainbow, ruby, scala, sh, sql, swift, visualbasic, xml, yamldiff --git a/node_modules/@janus-idp/backstage-plugin-keycloak-backend/dist/index.cjs.js b/node_modules/@janus-idp/backstage-plugin-keycloak-backend/dist/index.cjs.js index a0e323e..180abfc 100644 --- a/node_modules/@janus-idp/backstage-plugin-keycloak-backend/dist/index.cjs.js +++ b/node_modules/@janus-idp/backstage-plugin-keycloak-backend/dist/index.cjs.js @@ -153,17 +153,19 @@ async function getEntities(entities, config, logger, entityQuerySize = KEYCLOAK_ const rawEntityCount = await entities.count({ realm: config.realm }); const entityCount = typeof rawEntityCount === "number" ? rawEntityCount : rawEntityCount.count; const pageCount = Math.ceil(entityCount / entityQuerySize); - const entityPromises = Array.from( - { length: pageCount }, - (_, i) => entities.find({ - realm: config.realm, - max: entityQuerySize, - first: i * entityQuerySize - }).catch( - (err) => logger.warn("Failed to retieve Keycloak entities.", err) - ) - ); - const entityResults = (await Promise.all(entityPromises)).flat(); + const entityResults = []; + for (let i = 0; i < pageCount; i++) { + try { + const entitiesPage = await entities.find({ + realm: config.realm, + max: entityQuerySize, + first: i * entityQuerySize + }); + entityResults.push(...entitiesPage); + } catch (err) { + logger.warn("Failed to retrieve Keycloak entities.", err); + } + } return entityResults; } async function getAllGroupMembers(groups, groupId, config, options) { @@ -254,35 +256,36 @@ const readKeycloakRealm = async (client, config, logger, options) => { [] ); } - const kGroups = await Promise.all( - rawKGroups.map(async (g) => { - g.members = await getAllGroupMembers( - client.groups, - g.id, - config, - options - ); - if (isVersion23orHigher) { - if (g.subGroupCount > 0) { - g.subGroups = await client.groups.listSubGroups({ - parentId: g.id, - first: 0, - max: g.subGroupCount, - briefRepresentation: false, - realm: config.realm - }); - } - if (g.parentId) { - const groupParent = await client.groups.findOne({ - id: g.parentId, - realm: config.realm - }); - g.parent = groupParent?.name; - } + const kGroups = []; + for (const g of rawKGroups) { + g.members = await getAllGroupMembers( + client.groups, + g.id, + config, + options, + ); + + if (isVersion23orHigher) { + if (g.subGroupCount > 0) { + g.subGroups = await client.groups.listSubGroups({ + parentId: g.id, + first: 0, + max: g.subGroupCount, + briefRepresentation: false, + realm: config.realm, + }); + }? + if (g.parentId) { + const groupParent = await client.groups.findOne({ + id: g.parentId, + realm: config.realm, + }); + g.parent = groupParent?.name; } - return g; - }) - ); + } + + kGroups.push(g); + } const parsedGroups = await kGroups.reduce( async (promise, g) => { const partial = await promise;This issue body was partially generated by patch-package.
Upstream URL: https://github.com/janus-idp/backstage-plugins/issues/2471
- links to