scimgateway 4.2.10 → 4.2.12
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 +13 -0
- package/lib/scimdef-v1.js +27 -11
- package/lib/scimdef-v2.js +17 -3
- package/lib/scimgateway.js +41 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -326,6 +326,7 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
|
|
|
326
326
|
- **scim.version** - "1.1" or "2.0". Default is "2.0". For Symantec/Broadcom/CA Identity Manager "1.1" should be used.
|
|
327
327
|
|
|
328
328
|
- **scim.customSchema** - filename of JSON file located in `<package-root>\config\schemas` containing custom schema attributes, see configuration notes
|
|
329
|
+
**additional information**: Schemas, ServiceProviderConfig and ResourceType can be customized if `lib/scimdef-v2.js (or scimdef-v1.js)` exists. Original scimdef-v2.js/scimdef-v1.js can be copied from node_modules/scimgateway/lib to your plugin/lib and customized.
|
|
329
330
|
|
|
330
331
|
- **scim.skipTypeConvert** - true or false, default false. Multivalue attributes supporting types e.g. emails, phoneNumbers, ims, photos, addresses, entitlements and x509Certificates (but not roles, groups and members) will be become "type converted objects" when sent to modifyUser and createUser. This for simplicity of checking attributes included and also for the endpointMapper method (used by plugin-ldap and plugin-azure-ad), e.g.:
|
|
331
332
|
|
|
@@ -1169,6 +1170,18 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
|
|
|
1169
1170
|
|
|
1170
1171
|
## Change log
|
|
1171
1172
|
|
|
1173
|
+
### v4.2.12
|
|
1174
|
+
|
|
1175
|
+
[Added]
|
|
1176
|
+
|
|
1177
|
+
- Schemas, ServiceProviderConfig and ResourceType can be customized if `lib/scimdef-v2.js (or scimdef-v1.js)` exists. Original scimdef-v2.js/scimdef-v1.js can be copied from node_modules/scimgateway/lib to your plugin/lib and customized.
|
|
1178
|
+
|
|
1179
|
+
### v4.2.11
|
|
1180
|
+
|
|
1181
|
+
[Added]
|
|
1182
|
+
|
|
1183
|
+
- Plugin can set error statusCode returned by scimgateway through error message. Error message must then contain string `"statusCode":xxx` where xxx is HTTP status code e.g., 401. Plugin using REST will have statusCode automatically included in error message thrown by plugin. This could be useful for auth.PassThrough.
|
|
1184
|
+
|
|
1172
1185
|
### v4.2.10
|
|
1173
1186
|
|
|
1174
1187
|
[Fixed]
|
package/lib/scimdef-v1.js
CHANGED
|
@@ -11,23 +11,39 @@ module.exports.ServiceProviderConfigs = {
|
|
|
11
11
|
"bulk": {
|
|
12
12
|
"supported": false,
|
|
13
13
|
"maxOperations": 10000,
|
|
14
|
-
"maxPayloadSize":
|
|
14
|
+
"maxPayloadSize": 1048576
|
|
15
15
|
},
|
|
16
16
|
"filter": {
|
|
17
17
|
"supported": true,
|
|
18
|
-
"maxResults":
|
|
18
|
+
"maxResults": 200
|
|
19
19
|
},
|
|
20
20
|
"changePassword": { "supported": true },
|
|
21
21
|
"sort": { "supported": false },
|
|
22
|
-
"etag": { "supported":
|
|
23
|
-
"authenticationSchemes": [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
"etag": { "supported": false },
|
|
23
|
+
"authenticationSchemes": [
|
|
24
|
+
{
|
|
25
|
+
"type": "httpbasic",
|
|
26
|
+
"name": "HTTP Basic",
|
|
27
|
+
"description": "Authentication scheme using the HTTP Basic Standard",
|
|
28
|
+
"specURI": "http://www.rfc-editor.org/info/rfc2617",
|
|
29
|
+
"documentationUri": "https://elshaug.xyz",
|
|
30
|
+
"primary": true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "oauthbearertoken",
|
|
34
|
+
"name": "OAuth Bearer Token",
|
|
35
|
+
"description": "Authentication scheme using the OAuth Bearer Token Standard",
|
|
36
|
+
"specUri": "http://www.rfc-editor.org/info/rfc6750",
|
|
37
|
+
"documentationUri": "https://elshaug.xyz"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "oauth2",
|
|
41
|
+
"name": "OAuth v2.0",
|
|
42
|
+
"description": "Authentication Scheme using the OAuth Standard",
|
|
43
|
+
"specUri": "http://tools.ietf.org/html/rfc6749",
|
|
44
|
+
"documentationUri": "https://elshaug.xyz"
|
|
45
|
+
}
|
|
46
|
+
],
|
|
31
47
|
"xmlDataFormat": { "supported": false }
|
|
32
48
|
}
|
|
33
49
|
|
package/lib/scimdef-v2.js
CHANGED
|
@@ -27,15 +27,29 @@ module.exports.ServiceProviderConfigs = {
|
|
|
27
27
|
"etag": {
|
|
28
28
|
"supported": false
|
|
29
29
|
},
|
|
30
|
-
"documentationUri": "
|
|
30
|
+
"documentationUri": "https://elshaug.xyz",
|
|
31
31
|
"authenticationSchemes": [
|
|
32
32
|
{
|
|
33
|
+
"type": "httpbasic",
|
|
33
34
|
"name": "HTTP Basic",
|
|
34
35
|
"description": "Authentication scheme using the HTTP Basic Standard",
|
|
35
36
|
"specURI": "http://www.rfc-editor.org/info/rfc2617",
|
|
36
|
-
"documentationUri": "
|
|
37
|
-
"type": "httpbasic",
|
|
37
|
+
"documentationUri": "https://elshaug.xyz",
|
|
38
38
|
"primary": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "oauthbearertoken",
|
|
42
|
+
"name": "OAuth Bearer Token",
|
|
43
|
+
"description": "Authentication scheme using the OAuth Bearer Token Standard",
|
|
44
|
+
"specUri": "http://www.rfc-editor.org/info/rfc6750",
|
|
45
|
+
"documentationUri": "https://elshaug.xyz"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"type": "oauth2",
|
|
49
|
+
"name": "OAuth v2.0",
|
|
50
|
+
"description": "Authentication Scheme using the OAuth Standard",
|
|
51
|
+
"specUri": "http://tools.ietf.org/html/rfc6749",
|
|
52
|
+
"documentationUri": "https://elshaug.xyz"
|
|
39
53
|
}
|
|
40
54
|
],
|
|
41
55
|
"xmlDataFormat": { "supported": false }
|
package/lib/scimgateway.js
CHANGED
|
@@ -37,7 +37,8 @@ const ScimGateway = function () {
|
|
|
37
37
|
const stack = callsite()
|
|
38
38
|
const requester = stack[1].getFileName()
|
|
39
39
|
const pluginName = path.basename(requester, '.js')
|
|
40
|
-
const
|
|
40
|
+
const pluginDir = path.dirname(requester)
|
|
41
|
+
const configDir = path.join(pluginDir, '..', 'config')
|
|
41
42
|
const configFile = path.join(`${configDir}`, `${pluginName}.json`) // config name prefix same as pluging name prefix
|
|
42
43
|
let config = require(configFile).scimgateway
|
|
43
44
|
let extConfigErr
|
|
@@ -46,7 +47,7 @@ const ScimGateway = function () {
|
|
|
46
47
|
} catch (err) { extConfigErr = err }
|
|
47
48
|
|
|
48
49
|
const gwName = path.basename(__filename, '.js') // prefix of current file
|
|
49
|
-
const logDir = path.join(
|
|
50
|
+
const logDir = path.join(pluginDir, '..', 'logs')
|
|
50
51
|
const Log = require('../lib/logger').Log
|
|
51
52
|
const log = new Log(utils.extendObj(utils.copyObj(config.log), { category: pluginName, colorize: process.stdout.isTTY || false, loglevel: { file: (!config.log.loglevel.file || config.log.loglevel.file === 'off') ? null : 'debug', console: 'debug' } }), path.join(`${logDir}`, `${pluginName}.log`))
|
|
52
53
|
const logger = log.logger()
|
|
@@ -246,10 +247,14 @@ const ScimGateway = function () {
|
|
|
246
247
|
let isScimv2 = false
|
|
247
248
|
if (config.scim.version === '2.0' || config.scim.version === 2) {
|
|
248
249
|
isScimv2 = true
|
|
249
|
-
scimDef = require('
|
|
250
|
-
|
|
250
|
+
if (fs.existsSync(pluginDir + '/scimdef-v2.js')) scimDef = require(pluginDir + '/scimdef-v2') // using custom
|
|
251
|
+
else scimDef = require('../lib/scimdef-v2')
|
|
252
|
+
} else {
|
|
253
|
+
if (fs.existsSync(pluginDir + '/scimdef-v1.js')) scimDef = require(pluginDir + '/scimdef-v1') // using custom
|
|
254
|
+
else scimDef = require('../lib/scimdef-v1')
|
|
255
|
+
}
|
|
251
256
|
|
|
252
|
-
if (config.scim.customSchema) { // merge plugin custom schema extension into core schemas
|
|
257
|
+
if (config.scim.customSchema) { // merge plugin custom schema extension into core schemas (better using above custom scimdef-v2.js in plugin lib folder)
|
|
253
258
|
let custom
|
|
254
259
|
try {
|
|
255
260
|
custom = JSON.parse(fs.readFileSync(`${configDir}/schemas/${config.scim.customSchema}`, 'utf8'))
|
|
@@ -285,8 +290,15 @@ const ScimGateway = function () {
|
|
|
285
290
|
}
|
|
286
291
|
}
|
|
287
292
|
|
|
288
|
-
|
|
289
|
-
this.
|
|
293
|
+
// exposed and used by plugin-loki
|
|
294
|
+
this.testmodeusers = []
|
|
295
|
+
this.testmodegroups = []
|
|
296
|
+
if (scimDef.TestmodeUsers && scimDef.TestmodeUsers.Resources) {
|
|
297
|
+
this.testmodeusers = scimDef.TestmodeUsers.Resources
|
|
298
|
+
}
|
|
299
|
+
if (scimDef.TestmodeGroups && scimDef.TestmodeGroups.Resources) {
|
|
300
|
+
this.testmodegroups = scimDef.TestmodeGroups.Resources
|
|
301
|
+
}
|
|
290
302
|
|
|
291
303
|
// multiValueTypes array contains attributes that will be used by "type converted objects" logic
|
|
292
304
|
// groups, roles, and members are excluded
|
|
@@ -318,22 +330,35 @@ const ScimGateway = function () {
|
|
|
318
330
|
if (!userName && authType === 'Bearer') userName = 'token'
|
|
319
331
|
if (ctx.request.url !== '/favicon.ico') {
|
|
320
332
|
if (ctx.response.status < 200 || ctx.response.status > 299) {
|
|
321
|
-
|
|
333
|
+
// statusCode check in logResult method...
|
|
334
|
+
// "statusCode":xxx in error messages let plugin set error statusCode returned by scimgateway
|
|
335
|
+
let pluginStatusCode = 0
|
|
336
|
+
const reJson = '^.*"(statusCode)" *: *([0-9][0-9][0-9]).*'
|
|
337
|
+
const rePattern = new RegExp(reJson, 'i')
|
|
322
338
|
if (res.body.detail) {
|
|
323
|
-
|
|
339
|
+
const arrMatches = res.body.detail.match(rePattern)
|
|
340
|
+
if (Array.isArray(arrMatches) && arrMatches.length === 3) {
|
|
341
|
+
pluginStatusCode = parseInt(arrMatches[2])
|
|
342
|
+
}
|
|
324
343
|
} else if (res.body.Errors) {
|
|
325
|
-
if (Array.isArray(res.body.Errors) && res.body.Errors[0].description && res.body.Errors[0].description
|
|
326
|
-
|
|
344
|
+
if (Array.isArray(res.body.Errors) && res.body.Errors[0].description && res.body.Errors[0].description) {
|
|
345
|
+
const arrMatches = res.body.Errors[0].description.match(rePattern)
|
|
346
|
+
if (Array.isArray(arrMatches) && arrMatches.length === 3) {
|
|
347
|
+
pluginStatusCode = parseInt(arrMatches[2])
|
|
348
|
+
}
|
|
327
349
|
}
|
|
328
350
|
}
|
|
329
|
-
if (
|
|
330
|
-
ctx.response.
|
|
331
|
-
ctx.response.status = 401 // ctx.response.message becomes default 'Unauthorized'
|
|
332
|
-
ctx.response.body = { error: 'Access denied' }
|
|
351
|
+
if (pluginStatusCode > 0) {
|
|
352
|
+
ctx.response.status = pluginStatusCode // auto change ctx.response.message
|
|
333
353
|
res.statusCode = ctx.response.status
|
|
334
354
|
res.statusMessage = ctx.response.message
|
|
335
|
-
|
|
355
|
+
if (pluginStatusCode === 401 || pluginStatusCode === 403) { // don't reveal original SCIM error message details related to access denied (e.g. using Auth PassThrough)
|
|
356
|
+
ctx.response.set('Content-Type', 'application/json; charset=utf-8')
|
|
357
|
+
ctx.response.body = { error: 'Access denied' }
|
|
358
|
+
res.body = ctx.response.body
|
|
359
|
+
}
|
|
336
360
|
}
|
|
361
|
+
// back to logResult...
|
|
337
362
|
logger.error(`${gwName}[${pluginName}] ${ellapsed} ${ctx.request.ipcli} ${userName} ${ctx.request.method} ${ctx.request.href} Inbound = ${JSON.stringify(ctx.request.body)} Outbound = ${JSON.stringify(res)}${(config.log.loglevel.file === 'debug' && ctx.request.url !== '/ping') ? '\n' : ''}`)
|
|
338
363
|
} else logger.info(`${gwName}[${pluginName}] ${ellapsed} ${ctx.request.ipcli} ${userName} ${ctx.request.method} ${ctx.request.href} Inbound = ${JSON.stringify(ctx.request.body)} Outbound = ${JSON.stringify(res)}${(config.log.loglevel.file === 'debug' && ctx.request.url !== '/ping') ? '\n' : ''}`)
|
|
339
364
|
requestCounter += 1 // logged on exit (not win process termination)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scimgateway",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.12",
|
|
4
4
|
"description": "Using SCIM protocol as a gateway for user provisioning to other endpoints",
|
|
5
5
|
"author": "Jarle Elshaug <jarle.elshaug@gmail.com> (https://elshaug.xyz)",
|
|
6
6
|
"homepage": "https://elshaug.xyz",
|