scimgateway 6.1.20 → 6.2.0

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/README.md CHANGED
@@ -17,6 +17,7 @@
17
17
 
18
18
  Latest news:
19
19
 
20
+ - New `plugin-generic` replacing previous `plugin-scim`. This new plugin use the endpointMapper for flexible attribute mapping and also supports the new mapper option `valueMap` (e.g., group filtering and mapping).
20
21
  - Now supports `GET /Roles` and `GET /Entitlements` endpoint requests, with corresponding user management via the standard SCIM `roles` and `entitlements` attributes. The Entra ID plugin uses `entitlements` for Entra ID licenses (read-only) and `roles` for Entra ID Permanent and Eligible roles (full management).
21
22
  - Bun binary build is now supported, allowing SCIM Gateway to be compiled into a single executable binary for simplified deployment and execution. SCIM Gateway can now run as an ES module (TypeScript) in Node.js.
22
23
  - Major release **v6.0.0** introduces changes to API method responses (not SCIM-related) and a new method `publicApi()` for handling public path `/pub/api` requests with no authentication required. In addition, the configuration option `bearerJwtAzure.tenantIdGUID` has been replaced by `bearerJwt.azureTenantId`. See the version history for details.
@@ -61,7 +62,7 @@ The following fully functional plugins are included for demonstration and produc
61
62
  | **Loki** | NoSQL Database | Transforms the SCIM Gateway into a standalone SCIM endpoint utilizing the internal [LokiJS](https://github.com/techfort/LokiJS) database. Includes two test users and groups |
62
63
  | **MongoDB** | NoSQL Database | Similar to the Loki plugin, but using an externally managed MongoDB database, showcasing multi-tenant and multi-endpoint capabilities via `baseEntity` |
63
64
  | **Entra ID** | REST Webservices | Entra ID user provisioning via Microsoft Graph API |
64
- | **SCIM** | REST Webservice | Using plugin Loki as a SCIM provisioning endpoint. May become a SCIM version-gateway (e.g., 1.1 => 2.0) |
65
+ | **Generic** | REST Webservice | Generic template plugin configured to use plugin-loki as a SCIM provisioning endpoint. Supports the endpointMapper `valueMap` option for allowlisting and mapping (e.g., groups). Can also be used as a SCIM version gateway (e.g., 1.1 => 2.0) |
65
66
  | **API** | REST Webservices | A non-SCIM plugin demonstrating API Gateway functionality for custom REST specifications |
66
67
  | **Soap** | SOAP Webservice | Demonstrates user provisioning to a SOAP-based endpoint with example WSDLs |
67
68
  | **MSSQL** | Database | Demonstrates user provisioning to an MSSQL database |
@@ -1304,12 +1305,52 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
1304
1305
 
1305
1306
  ## Change log
1306
1307
 
1308
+ ### v6.2.0
1309
+
1310
+ [Fixed]
1311
+
1312
+ - `helper-rest` failed on Bun v1.3.14 due to stricter compliance with Fetch standards.
1313
+
1314
+ [Improved]
1315
+
1316
+ - New `plugin-generic` replacing previous `plugin-scim`. This new plugin use the endpointMapper for flexible attribute mapping and also supports the new mapper option `valueMap` (e.g., group filtering and mapping). The default configuration uses one-to-one SCIM mapping, with plugin-loki as the target SCIM endpoint.
1317
+ - endpointMapper now supports the 'valueMap' option
1318
+
1319
+ Example configuration:
1320
+
1321
+ "map": {
1322
+ "group": {
1323
+ ...
1324
+ "displayName": {
1325
+ "mapTo": "displayName",
1326
+ "type": "string",
1327
+ "valueMap": {
1328
+ "outboundEndpointGrp1": "inboundScimGrp1",
1329
+ "Employees": "Admins"
1330
+ }
1331
+ },
1332
+ ...
1333
+ }
1334
+ ...
1335
+ }
1336
+
1337
+ Using the above settings restricts the client using SCIM Gateway with regard to group management.
1338
+ The client will only see and be able to manage groups with SCIM names "inboundScimGrp1" and "Admins",
1339
+ if their mapped counterparts exist at the target endpoint as "outboundEndpointGrp1" and "Employees".
1340
+
1341
+ Use case:
1342
+
1343
+ - Allowlisting specific groups or user objects that includes attribute mapping having the valueMap option configured.
1344
+ - Supporting different inbound/outbound names (e.g., Entra ID group provisioning to SCIM Gateway).
1345
+
1346
+
1307
1347
  ### v6.1.20
1308
1348
 
1309
1349
  [Fixed]
1310
1350
 
1311
1351
  - plugin-entra-id: Roles introduced in v6.1.19 were missing when retrieving a single user.
1312
1352
 
1353
+
1313
1354
  ### v6.1.19
1314
1355
 
1315
1356
  [Fixed]
@@ -156,6 +156,69 @@
156
156
  }
157
157
  }
158
158
  }
159
+ },
160
+ "map": {
161
+ "group": {
162
+ "id": {
163
+ "mapTo": "id",
164
+ "type": "string"
165
+ },
166
+ "displayName": {
167
+ "mapTo": "displayName",
168
+ "type": "string",
169
+ "valueMap": {}
170
+ },
171
+ "members": {
172
+ "mapTo": "members",
173
+ "type": "complexArray"
174
+ }
175
+ },
176
+ "user": {
177
+ "id": {
178
+ "mapTo": "id",
179
+ "type": "string"
180
+ },
181
+ "userName": {
182
+ "mapTo": "userName",
183
+ "type": "string",
184
+ "xvalueMap": {
185
+ "bjensen": "Xbjensen"
186
+ }
187
+ },
188
+ "active": {
189
+ "mapTo": "active",
190
+ "type": "boolean"
191
+ },
192
+ "password": {
193
+ "mapTo": "password",
194
+ "type": "string"
195
+ },
196
+ "title": {
197
+ "mapTo": "title",
198
+ "type": "string"
199
+ },
200
+ "name": {
201
+ "mapTo": "name",
202
+ "type": "complexObject",
203
+ "subAttributes": []
204
+ },
205
+ "emails": {
206
+ "mapTo": "emails",
207
+ "type": "complexArray"
208
+ },
209
+ "phoneNumbers": {
210
+ "mapTo": "phoneNumbers",
211
+ "type": "complexArray"
212
+ },
213
+ "roles": {
214
+ "mapTo": "roles",
215
+ "type": "complexArray"
216
+ },
217
+ "entitlements": {
218
+ "mapTo": "entitlements",
219
+ "type": "complexArray"
220
+ }
221
+ }
159
222
  }
160
223
  }
161
224
  }
package/index.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  //
13
13
 
14
14
  // start one or more plugins:
15
- // import './lib/plugin-scim.ts'
15
+ // import './lib/plugin-generic.ts'
16
16
  // import './lib/plugin-entra-id.ts'
17
17
  // import './lib/plugin-ldap.ts'
18
18
  // import './lib/plugin-mongodb.ts'
@@ -702,6 +702,11 @@ export class HelperRest {
702
702
  }
703
703
  }
704
704
 
705
+ // Bun v1.3.14 became stricter and more aligned with standards.
706
+ delete options.host
707
+ delete options.port
708
+ delete options.protocol
709
+
705
710
  // execute request
706
711
  const f = await fetch(url, options)
707
712
  if (!f.status) throw new Error('Response missing status code')
@@ -294,6 +294,7 @@ scimgateway.getUsers = async (baseEntity, getObj, attributes, ctx) => {
294
294
  if (!path) throw new Error(`${action} error: mandatory if-else logic not fully implemented`)
295
295
 
296
296
  if (path.includes('$count=true')) { // $count=true requires ConsistencyLevel
297
+ // note: when using $expand, the $count=true might be ignored by target endpoint and the ctx.paging.totalResults updated by doReqest() will be incremental
297
298
  if (!options.headers) options.headers = {}
298
299
  options.headers.ConsistencyLevel = 'eventual'
299
300
  }
@@ -730,6 +731,7 @@ scimgateway.getGroups = async (baseEntity, getObj, attributes, ctx) => {
730
731
  if (!path) throw new Error(`${action} error: mandatory if-else logic not fully implemented`)
731
732
 
732
733
  if (path.includes('$count=true')) { // $count=true requires ConsistencyLevel
734
+ // note: when using $expand, the $count=true might be ignored by target endpoint and the ctx.paging.totalResults updated by doReqest() will be incremental
733
735
  if (!options.headers) options.headers = {}
734
736
  options.headers.ConsistencyLevel = 'eventual'
735
737
  }
@@ -1357,7 +1359,6 @@ const getUserRoles = async (baseEntity: string, userId: string, groups: Record<s
1357
1359
  })
1358
1360
 
1359
1361
  const permanentRoles = rolesAssignments.permanent.filter((role: any) => Ids.includes(role.principalId)).map((role: any) => {
1360
- if (eligibleRoles.filter((r: any) => r.value === role.roleDefinitionId).length > 0) return null // eligible role activated becomes listed as permanent, skip those...
1361
1362
  const roleDef = roleDefs[role.roleDefinitionId]
1362
1363
  if (roleDef) {
1363
1364
  if (includeAssignmentId === true) return { type: 'Permanent', value: roleDef.id, display: roleDef.displayName, assignmentId: role.id }