scimgateway 5.2.2 → 5.2.4
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 +21 -5
- package/lib/scimgateway.ts +27 -3
- package/package.json +1 -1
- package/test/lib/plugin-loki_test.ts +12 -2
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Latest news:
|
|
|
18
18
|
|
|
19
19
|
- Remote real-time log subscription for monitoring and centralized logging
|
|
20
20
|
using browser and url: https://host/logger
|
|
21
|
-
curl -N https://host/logger -u
|
|
21
|
+
curl -N https://host/logger -u user:password
|
|
22
22
|
custom client API, see configuration notes
|
|
23
23
|
- By configuring the chainingBaseUrl, it is now possible to chain multiple gateways in sequence, such as `gateway1->gateway2->gateway3->endpoint`. In this setup, gateway beave much like a reverse proxy, validating authorization at each step unless PassThrough mode is enabled. Chaining is also supported in stream subscriber mode
|
|
24
24
|
- Email, onError and sendMail() supports more secure RESTful OAuth for Microsoft Exchange Online (ExO) and Google Workspace Gmail, alongside traditional SMTP Auth for all mail systems. HelperRest supports a wide range of common authentication methods, including basicAuth, bearerAuth, tokenAuth, oauth, oauthSamlBearer, oauthJwtBearer and Auth PassTrough
|
|
@@ -395,6 +395,8 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
|
|
|
395
395
|
|
|
396
396
|
- **log.loglevel.push** - off, debug, info, warn or error. Default info. Push to stream that can be used by client subscriber
|
|
397
397
|
|
|
398
|
+
- **log.logDirectory** - custom defined log directory e.g. `/var/log/scimgateway` that will override default `<scimgateway path>/logs`. If not exist it will be created.
|
|
399
|
+
|
|
398
400
|
- **log.customMasking** - array of attributes to be masked e.g. `"customMasking": ["SSN", "weight"]`. By default SCIM Gateway includes masking of some standard attributes like password.
|
|
399
401
|
|
|
400
402
|
- **log.colorize** - default true, gives colorized and minimized console output, if redirected to stdout/stderr standard JSON formatted output and no colors. Set to false give standard JSON
|
|
@@ -695,7 +697,7 @@ Example Entra ID (plugin-entra-id) using clientId/clientSecret:
|
|
|
695
697
|
"type": "oauth",
|
|
696
698
|
"options": {
|
|
697
699
|
"tenantIdGUID": "<tenantId>",
|
|
698
|
-
"clientId": "<clientId",
|
|
700
|
+
"clientId": "<clientId>",
|
|
699
701
|
"clientSecret": "<clientSecret>"
|
|
700
702
|
}
|
|
701
703
|
}
|
|
@@ -709,7 +711,7 @@ Example Entra ID (plugin-entra-id) using certificate secret:
|
|
|
709
711
|
"type": "oauth",
|
|
710
712
|
"options": {
|
|
711
713
|
"tenantIdGUID": "<tenantId>",
|
|
712
|
-
"clientId": "<clientId",
|
|
714
|
+
"clientId": "<clientId>",
|
|
713
715
|
"tls": {
|
|
714
716
|
"key": "key.pem",
|
|
715
717
|
"cert": "cert.pem"
|
|
@@ -726,7 +728,7 @@ Example using general OAuth:
|
|
|
726
728
|
"type": "oauth",
|
|
727
729
|
"options": {
|
|
728
730
|
"tokenUrl": "<tokenUrl>"
|
|
729
|
-
"clientId": "<clientId",
|
|
731
|
+
"clientId": "<clientId>",
|
|
730
732
|
"clientSecret": "<clientSecret>"
|
|
731
733
|
}
|
|
732
734
|
}
|
|
@@ -819,7 +821,7 @@ Example code implementing subscriber for real-time log messages collection
|
|
|
819
821
|
console.error('error', e)
|
|
820
822
|
|
|
821
823
|
} catch (err: any) {
|
|
822
|
-
if (['ConnectionClosed', 'ConnectionRefused'].includes(err.code)) {
|
|
824
|
+
if (['ConnectionClosed', 'ConnectionRefused', 'ECONNRESET'].includes(err.code)) {
|
|
823
825
|
console.log('Connection closed or service unavailable')
|
|
824
826
|
ignoreCatch = true
|
|
825
827
|
await Bun.sleep(10 * 1000)
|
|
@@ -1401,6 +1403,20 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
|
|
|
1401
1403
|
|
|
1402
1404
|
## Change log
|
|
1403
1405
|
|
|
1406
|
+
### v5.2.4
|
|
1407
|
+
|
|
1408
|
+
[Improved]
|
|
1409
|
+
|
|
1410
|
+
- New configuration `log.logDirectory` for custom defined log directory e.g. `/var/log/scimgateway` that will override default `<scimgateway path>/logs`.
|
|
1411
|
+
**Thanks to [@Gerrit Lansing](https://github.com/gerritlansing)**
|
|
1412
|
+
- Base URL like `/scim/v1` and `/scim/v2` is now supported, also with baseEntity e.g. `/scim/v2/client1/Users`
|
|
1413
|
+
|
|
1414
|
+
### v5.2.3
|
|
1415
|
+
|
|
1416
|
+
[Fixed]
|
|
1417
|
+
|
|
1418
|
+
- GET /ResourceTypes was missing in v5
|
|
1419
|
+
|
|
1404
1420
|
### v5.2.2
|
|
1405
1421
|
|
|
1406
1422
|
[Fixed]
|
package/lib/scimgateway.ts
CHANGED
|
@@ -334,7 +334,6 @@ export class ScimGateway {
|
|
|
334
334
|
const configFile = path.join(`${configDir}`, `${pluginName}.json`) // config name prefix same as pluging name prefix
|
|
335
335
|
const gwName = path.basename(fileURLToPath(import.meta.url)).split('.')[0] // prefix of current file - using fileURLToPath because using "__filename" is not supported by nodejs typescript
|
|
336
336
|
const gwPath = path.dirname(fileURLToPath(import.meta.url))
|
|
337
|
-
const logDir = path.join(pluginDir, '..', 'logs')
|
|
338
337
|
|
|
339
338
|
this.config = {}
|
|
340
339
|
// exposed outside class
|
|
@@ -356,6 +355,7 @@ export class ScimGateway {
|
|
|
356
355
|
found = this.processConfig()
|
|
357
356
|
} catch (err) { configErr = err }
|
|
358
357
|
|
|
358
|
+
const logDir = this.config?.scimgateway?.log?.logDirectory || path.join(pluginDir, '..', 'logs')
|
|
359
359
|
const logger = new Logger(
|
|
360
360
|
pluginName,
|
|
361
361
|
{
|
|
@@ -483,7 +483,7 @@ export class ScimGateway {
|
|
|
483
483
|
getMethod: 'getAppRoles',
|
|
484
484
|
}
|
|
485
485
|
/** handlers supported url paths */
|
|
486
|
-
const handlers = ['users', 'groups', 'serviceplans', 'approles', 'api', 'schemas', 'serviceproviderconfig', 'serviceproviderconfigs', 'logger']
|
|
486
|
+
const handlers = ['users', 'groups', 'serviceplans', 'approles', 'api', 'schemas', 'resourcetypes', 'serviceproviderconfig', 'serviceproviderconfigs', 'logger']
|
|
487
487
|
|
|
488
488
|
try {
|
|
489
489
|
if (!fs.existsSync(configDir + '/wsdls')) fs.mkdirSync(configDir + '/wsdls')
|
|
@@ -832,6 +832,21 @@ export class ScimGateway {
|
|
|
832
832
|
}
|
|
833
833
|
funcHandler.getHandlerSchemas = getHandlerSchemas
|
|
834
834
|
|
|
835
|
+
// scimv2 GET /ResourceTypes, scimv1 not used
|
|
836
|
+
const getHandlerResourceTypes = async (ctx: Context) => {
|
|
837
|
+
const tx = this.scimDef.ResourceType
|
|
838
|
+
if (!this.config.scimgateway.scim.skipMetaLocation) {
|
|
839
|
+
const location = ctx.origin + ctx.path
|
|
840
|
+
if (tx.meta) tx.meta.location = location
|
|
841
|
+
else {
|
|
842
|
+
tx.meta = {}
|
|
843
|
+
tx.meta.location = location
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
ctx.response.body = JSON.stringify(tx)
|
|
847
|
+
}
|
|
848
|
+
funcHandler.getHandlerResourceTypes = getHandlerResourceTypes
|
|
849
|
+
|
|
835
850
|
// scimv1 = GET /ServiceProviderConfigs, scimv2 GET /ServiceProviderConfig
|
|
836
851
|
const getHandlerServiceProviderConfig = async (ctx: Context) => {
|
|
837
852
|
const tx = this.scimDef.ServiceProviderConfigs
|
|
@@ -2159,7 +2174,13 @@ export class ScimGateway {
|
|
|
2159
2174
|
const method = request.method
|
|
2160
2175
|
const url = new URL(request.url)
|
|
2161
2176
|
|
|
2162
|
-
let
|
|
2177
|
+
let pathname = url.pathname
|
|
2178
|
+
const match = pathname.match(/.*\/scim\/v(1|2)(\/.*)/)
|
|
2179
|
+
if (match) {
|
|
2180
|
+
pathname = match[2] // the part after /scim/vX
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
let [, baseEntity, handle, id, rest]: string[] = pathname.split('/')
|
|
2163
2184
|
if (baseEntity && handlers.includes(baseEntity.toLowerCase())) {
|
|
2164
2185
|
rest = id
|
|
2165
2186
|
id = handle
|
|
@@ -2414,6 +2435,9 @@ export class ScimGateway {
|
|
|
2414
2435
|
case 'GET schemas':
|
|
2415
2436
|
await getHandlerSchemas(ctx)
|
|
2416
2437
|
return await onAfterHandle(ctx)
|
|
2438
|
+
case 'GET resourcetypes':
|
|
2439
|
+
await getHandlerResourceTypes(ctx)
|
|
2440
|
+
return await onAfterHandle(ctx)
|
|
2417
2441
|
case 'GET serviceproviderconfig':
|
|
2418
2442
|
case 'GET serviceproviderconfigs':
|
|
2419
2443
|
await getHandlerServiceProviderConfig(ctx)
|
package/package.json
CHANGED
|
@@ -32,8 +32,8 @@ async function fetchSCIM(method: string, endpoint: string, body?: any, headers?:
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
describe('plugin-loki', async () => {
|
|
35
|
-
test('
|
|
36
|
-
const response: any = await fetchSCIM('GET', '/
|
|
35
|
+
test('ServiceProviderConfig test', async () => {
|
|
36
|
+
const response: any = await fetchSCIM('GET', '/ServiceProviderConfig', undefined, options.std.headers)
|
|
37
37
|
expect(response.status).toBe(200)
|
|
38
38
|
expect(response.body.schemas).toContain('urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig')
|
|
39
39
|
})
|
|
@@ -48,6 +48,16 @@ describe('plugin-loki', async () => {
|
|
|
48
48
|
})
|
|
49
49
|
})
|
|
50
50
|
|
|
51
|
+
test('ResourceTypes test', async () => {
|
|
52
|
+
const response: any = await fetchSCIM('GET', '/ResourceTypes', undefined, options.std.headers)
|
|
53
|
+
expect(response.status).toBe(200)
|
|
54
|
+
expect(Array.isArray(response.body.Resources)).toBe(true)
|
|
55
|
+
expect(response.body.Resources.length).toEqual(2)
|
|
56
|
+
expect(response.body.Resources[0].schemas).toContain('urn:ietf:params:scim:schemas:core:2.0:ResourceType')
|
|
57
|
+
expect(response.body.Resources[0].id).toBe('urn:ietf:params:scim:schemas:core:2.0:User')
|
|
58
|
+
expect(response.body.Resources[1].id).toBe('urn:ietf:params:scim:schemas:core:2.0:Group')
|
|
59
|
+
})
|
|
60
|
+
|
|
51
61
|
test('getUsers all test (1)', async () => {
|
|
52
62
|
const response: any = await fetchSCIM('GET', '/Users?startIndex=1&count=100', undefined, options.std.headers)
|
|
53
63
|
const users = response?.body
|