scimgateway 5.0.15 → 5.1.1

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.
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
@@ -0,0 +1,28 @@
1
+ name: Test Master Branch
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - master
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v3
18
+
19
+ - name: Install Bun
20
+ run: |
21
+ curl -fsSL https://bun.sh/install | bash
22
+ echo "$HOME/.bun/bin" >> $GITHUB_PATH
23
+
24
+ - name: Install dependencies
25
+ run: bun install
26
+
27
+ - name: Run master tests
28
+ run: bun run test
@@ -0,0 +1,25 @@
1
+ name: Test Release Workflow
2
+
3
+ on:
4
+ release:
5
+ types:
6
+ - published
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v3
15
+
16
+ - name: Install Bun
17
+ run: |
18
+ curl -fsSL https://bun.sh/install | bash
19
+ echo "$HOME/.bun/bin" >> $GITHUB_PATH
20
+
21
+ - name: Install dependencies
22
+ run: bun install
23
+
24
+ - name: Run release tests
25
+ run: bun run test
package/.travis.yml CHANGED
@@ -13,4 +13,4 @@ install:
13
13
 
14
14
  # Run the Bun test runner
15
15
  script:
16
- - bun test
16
+ - bun run test
package/README.md CHANGED
@@ -16,6 +16,7 @@ Validated through IdP's:
16
16
 
17
17
  Latest news:
18
18
 
19
+ - 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
19
20
  - 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
20
21
  - Major version **v5.0.0** marks a shift to native TypeScript support and prioritizes [Bun](https://bun.sh/) over Node.js. This upgrade requires some modifications to existing plugins.
21
22
  - **BREAKING**: [SCIM Stream](https://elshaug.xyz/docs/scim-stream) is the modern way of user provisioning letting clients subscribe to messages instead of traditional IGA top-down provisioning. SCIM Gateway now offers enhanced functionality with support for message subscription and automated provisioning using SCIM Stream
@@ -58,10 +59,8 @@ Shows how to implement a highly configurable multi tenant or multi endpoint solu
58
59
 
59
60
  * **SCIM** (REST Webservice)
60
61
  Demonstrates user provisioning towards REST-Based endpoint (type SCIM)
61
- Using plugin Loki as SCIM endpoint
62
+ Using plugin Loki as SCIM endpoint through HelperRest
62
63
  Can be used as SCIM version-gateway e.g. 1.1=>2.0 or 2.0=>1.1
63
- Can be used to chain several gateways
64
-
65
64
 
66
65
  * **Soap** (SOAP Webservice)
67
66
  Demonstrates user provisioning towards SOAP-Based endpoint
@@ -77,7 +76,7 @@ Demonstrates SAP HANA specific user provisioning
77
76
 
78
77
  * **Entra ID** (REST Webservices)
79
78
  Entra ID user provisioning including license management (App Service plans) e.g. Office 365
80
- Using Microsoft Graph API
79
+ Using Microsoft Graph API through HelperRest
81
80
  Using customized SCIM attributes according to Microsoft Graph API
82
81
  Includes Symantec/Broadcom/CA ConnectorXpress metafile for creating provisioning "Azure - ScimGateway" endpoint type
83
82
 
@@ -87,7 +86,7 @@ Pre-configured for Microsoft Active Directory
87
86
  Using endpointMapper (like plugin-entra-id) for attribute mapping flexibility
88
87
 
89
88
  * **API** (REST Webservices)
90
- Demonstrates API Gateway/plugin functionality using post/put/patch/get/delete
89
+ Demonstrates API Gateway/plugin functionality using post/put/patch/get/delete combined with HelperRest
91
90
  None SCIM plugin, becomes what you want it to become.
92
91
  Methods included can also be used in standard SCIM plugins
93
92
  Endpoint complexity could be put in this plugin, and client could instead communicate through Gateway using your own simplified REST specification.
@@ -185,7 +184,7 @@ For Node.js (and also Bun), we might set the property `scimgateway_postinstall_s
185
184
  // example starting all default plugins:
186
185
  // const plugins = ['loki', 'scim', 'entra-id', 'ldap', 'mssql', 'api', 'mongodb', 'saphana', 'soap']
187
186
 
188
- const plugins = ['ldap']
187
+ const plugins = ['loki']
189
188
 
190
189
  for (const plugin of plugins) {
191
190
  try {
@@ -209,6 +208,7 @@ Below shows an example of config\plugin-saphana.json
209
208
  "scimgateway": {
210
209
  "port": 8884,
211
210
  "localhostonly": false,
211
+ "chainingBaseUrl": null,
212
212
  "scim": {
213
213
  "version": "2.0",
214
214
  "skipTypeConvert" : false,
@@ -354,6 +354,8 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
354
354
 
355
355
  - **localhostonly** - true or false. False means gateway accepts incoming requests from all clients. True means traffic from only localhost (127.0.0.1) is accepted.
356
356
 
357
+ - **chainingBaseUrl** - baseUrl for chaining anohter gateway, syntax: `http(s)://host:port`. If defined, gateway beave much like a reverse proxy, validating authorization unless PassThrough mode is enabled. See `Configuration notes` for details
358
+
357
359
  - **idleTimeout** - default 120, sets the the number of seconds to wait before timing out a connection due to inactivity
358
360
 
359
361
  - **scim.version** - "1.1" or "2.0". Default is "2.0".
@@ -399,7 +401,7 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
399
401
 
400
402
  - **auth.bearerJwt** - Array of one or more standard JWT objects. Using **secret** or **publicKey** for signature verification. publicKey should be set to the filename of public key or certificate pem-file located in `<package-root>\config\certs` or absolute path being used. Clear text secret will become encrypted when gateway is started. **options.issuer** is mandatory. Other options may also be included according to jsonwebtoken npm package definition.
401
403
 
402
- - **auth.bearerOAuth** - Array of one or more Client Credentials OAuth configuration objects. **`clientId`** and **`clientSecret`** are mandatory. clientSecret value will become encrypted when gateway is started. OAuth token request url is **/oauth/token** e.g. http://localhost:8880/oauth/token
404
+ - **auth.bearerOAuth** - Array of one or more Client Credentials OAuth configuration objects. **`clientId`** and **`clientSecret`** are mandatory. clientSecret value will become encrypted when gateway is started. OAuth token request url is **/oauth/token** e.g. `http://localhost:8880/oauth/token`
403
405
 
404
406
  - **auth.passThrough** - Setting **auth.passThrough.enabled=true** will bypass SCIM Gateway authentication. Gateway will instead pass ctx containing authentication header to the plugin. Plugin could then use this information for endpoint authentication and we don't have any password/token stored at the gateway. Note, this also requires plugin binary having `scimgateway.authPassThroughAllowed = true` and endpoint logic for handling/passing ctx.request.header.authorization
405
407
 
@@ -441,9 +443,9 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
441
443
  - **email.auth** - Authentication configuration
442
444
  - **email.auth.type** - `oauth` or `smtp`
443
445
  - **email.auth.options** - Authentication options - note, different options for type oauth and smtp
444
- - **email.auth.options.tenantIdGUID (oauth/ExO)** - Entra ID tenant id, mandatory/recommended when using Microsoft Exchange Online
445
- - **email.auth.options.clientId (oauth/ExO)** - Client ID
446
- - **email.auth.options.clientSecret (oauth/ExO)** - Client Secret
446
+ - **email.auth.options.tenantIdGUID (oauth/ExO)** - Entra tenant id or domain name
447
+ - **email.auth.options.clientId (oauth/ExO)** - Entra OAuth application Client ID
448
+ - **email.auth.options.clientSecret (oauth/ExO)** - Entra OAuth application Client Secret
447
449
  - **email.auth.options.serviceAccountKeyFile (oauth/Gmail)** - Google Service Account key json-file name located in the `package-root>\config\certs` directory unless absolute path being defined
448
450
  - **email.auth.options.host (smtp)** - Mailserver e.g. "smtp.gmail.com" - mandatory for smtp
449
451
  - **email.auth.options.port (smtp)** - Port used by mailserver e.g. 587, 25 or 465 - mandatory for smtp
@@ -561,6 +563,50 @@ Definitions in `endpoint` object are customized according to our plugin code. Pl
561
563
  - Licenses > Edit > enable Google Workspace license
562
564
  `email.emailOnError.from` mail address must have Google Workspace license
563
565
 
566
+ - Gateway chainging and chainingBaseUrl configuration
567
+
568
+ By configuring the `chainingBaseUrl`, it is possible to chain multiple gateways in sequence, such as `gateway1->gateway2->gateway3->endpoint`. In this setup, gateway behave much like a reverse proxy, validating authorization at each step unless PassThrough mode is enabled. Chaining is also supported in stream subscriber mode
569
+
570
+ {
571
+ "scimgateway": {
572
+ ...
573
+ "chainingBaseUrl": "https:\\gateway2:8880",
574
+ ...
575
+ "auth": {
576
+ ...
577
+ "passThrough": {
578
+ "enabled": false,
579
+ "readOnly": false,
580
+ "baseEntities": []
581
+ }
582
+ ...
583
+ }
584
+ },
585
+ ...
586
+ }
587
+
588
+
589
+ Using above configuration example on gateway1, incoming requests will be routed to `https:\\gateway2:8880`
590
+
591
+ The plugin and its associated authentication configuration can mirror the setup running on the final gateway. However, in chaining mode, the plugin binary is used solely for initializing and configuring the gateway. This allows for the use of a simplified `plugin-<name>.ts` binary containing only the essential mandatory components:
592
+
593
+ // start - mandatory plugin initialization
594
+ const ScimGateway: typeof import('scimgateway').ScimGateway = await (async () => {
595
+ try {
596
+ return (await import('scimgateway')).ScimGateway
597
+ } catch (err) {
598
+ const source = './scimgateway.ts'
599
+ return (await import(source)).ScimGateway
600
+ }
601
+ })()
602
+ const scimgateway = new ScimGateway()
603
+ const config = scimgateway.getConfig()
604
+ scimgateway.authPassThroughAllowed = false
605
+ // end - mandatory plugin initialization
606
+
607
+ Using `scimgateway.authPassThroughAllowed = true` and `plugin-<name>.json` configuration `scimgateway.auth.passThrough=true` enables Authentication PassTrhough
608
+
609
+
564
610
 
565
611
  ## Manual startup
566
612
 
@@ -1136,6 +1182,21 @@ MIT © [Jarle Elshaug](https://www.elshaug.xyz)
1136
1182
 
1137
1183
  ## Change log
1138
1184
 
1185
+ ### v5.1.1
1186
+
1187
+ [Fixed]
1188
+
1189
+ - SCIM Gateway failed to start on linux using Bun >= v1.1.43
1190
+
1191
+ ### v5.1.0
1192
+
1193
+ [Improved]
1194
+
1195
+ - 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
1196
+
1197
+ Please see `Configuration notes` for details
1198
+
1199
+
1139
1200
  ### v5.0.15
1140
1201
 
1141
1202
  [Improved]
package/bun.lockb CHANGED
Binary file
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8890,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8881,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "customSchema": null,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8883,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8880,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8885,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8888,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8884,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8886,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -2,6 +2,7 @@
2
2
  "scimgateway": {
3
3
  "port": 8882,
4
4
  "localhostonly": false,
5
+ "chainingBaseUrl": null,
5
6
  "scim": {
6
7
  "version": "2.0",
7
8
  "skipTypeConvert": false,
@@ -1,8 +1,17 @@
1
+ // =================================================================================
2
+ // File: helper-rest.ts
3
+ //
4
+ // Author: Jarle Elshaug
5
+ //
6
+ // Purpose: HelperRest class for executing REST calls supporting various auth types
7
+ // Plugins may use this class: import { HelperRest } from 'scimgateway'
8
+ // =================================================================================
9
+
1
10
  import { HttpsProxyAgent } from 'https-proxy-agent'
2
11
  import { URL } from 'url'
3
12
  import { Buffer } from 'node:buffer'
4
- import { samlAssertion } from './samlAssertion.ts' // prereq: saml
5
- import { sign as jwtSign } from 'jsonwebtoken'
13
+ import { samlAssertion } from './samlAssertion.ts'
14
+ import * as jsonwebtoken from 'jsonwebtoken'
6
15
  import fs from 'node:fs'
7
16
  import querystring from 'querystring'
8
17
  import * as utils from './utils.ts'
@@ -164,7 +173,7 @@ export class HelperRest {
164
173
 
165
174
  form = {
166
175
  grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
167
- assertion: jwtSign(jwtAttr, privateKey, { algorithm: 'RS256' }),
176
+ assertion: jsonwebtoken.sign(jwtAttr, privateKey, { algorithm: 'RS256' }),
168
177
  }
169
178
  break
170
179
 
@@ -428,9 +437,9 @@ export class HelperRest {
428
437
  return cli // final client
429
438
  }
430
439
  //
431
- // url path - none config based and used as is (no cache)
440
+ // url path - none config based (enpoint.entity) and used as is (no cache)
432
441
  //
433
- this.scimgateway.logDebug(baseEntity, `${action}: Using none config based client`)
442
+ this.scimgateway.logDebug(baseEntity, `${action}: Using raw client`)
434
443
  let options: any = {
435
444
  json: true,
436
445
  headers: {
@@ -440,7 +449,7 @@ export class HelperRest {
440
449
  port: urlObj.port,
441
450
  protocol: urlObj.protocol,
442
451
  method: method,
443
- path: urlObj.pathname,
452
+ path: urlObj.pathname + urlObj.search,
444
453
  }
445
454
 
446
455
  // proxy
@@ -516,7 +525,6 @@ export class HelperRest {
516
525
  const timeout = setTimeout(() => controller.abort(), options.abortTimeout ? options.abortTimeout * 1000 : this.idleTimeout * 1000) // 120 seconds default abort timeout
517
526
  options.signal = signal
518
527
  const url = `${options.protocol}//${options.host}${options.port ? ':' + options.port : ''}${options.path}`
519
- if (path.includes(')?$') && !options.headers['Accept-Encoding']) options.headers['Accept-Encoding'] = 'identity' // workaround for bun fetch error: "Decompression error: ShortRead" - have seen this error using OData with "<some-path>('xxx')?$expand=" or "<some-path>('xxx')?$select=" ref: https://github.com/oven-sh/bun/issues/8017
520
528
  // execute request
521
529
  const f = await fetch(url, options)
522
530
  clearTimeout(timeout)
@@ -1,4 +1,5 @@
1
1
  //
2
+ // File: samlAssertion.ts
2
3
  // Purpose: create SAML token assertion that can be used by OAuth token request having grant type saml2-bearer
3
4
  // Based on: https://github.com/edersouza38/insomnia-plugin-sfsf-samlassertion
4
5
  //