@openziti/ziti-sdk-nodejs 0.28.1 → 0.29.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/configure CHANGED
@@ -12,3 +12,4 @@ else
12
12
  fi
13
13
 
14
14
  ${basedir}/node_modules/.bin/cmake-js configure ${arch_arg} -- --preset=${preset}
15
+ # ${basedir}/node_modules/.bin/cmake-js configure ${arch_arg} -- --preset=${preset} -DZITI_SDK_DIR=/Users/curt/Repos/nf/github/ziti-sdk-c
@@ -0,0 +1,36 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ /**
18
+ * Provide an external JWT token to authenticate with the Ziti Controller.
19
+ *
20
+ * This function is used when the Ziti identity requires external authentication
21
+ * (e.g., OIDC). The auth event callback provided to init() will be called with
22
+ * the authentication details, and this function should be called with the JWT
23
+ * obtained from the external identity provider.
24
+ *
25
+ * @param {string} jwtToken - The JWT token obtained from the external identity provider
26
+ * @returns {number} 0 on success, -22 (ZITI_INVALID_STATE) if context not initialized
27
+ * @throws {Error} If jwtToken is not a non-empty string
28
+ */
29
+ const extAuthToken = (jwtToken) => {
30
+ if (typeof jwtToken !== 'string' || jwtToken.length === 0) {
31
+ throw new Error('JWT token must be a non-empty string');
32
+ }
33
+ return ziti.ziti_ext_auth_token(jwtToken);
34
+ };
35
+
36
+ exports.extAuthToken = extAuthToken;
@@ -61,7 +61,7 @@ const httpRequest = ( serviceName, schemeHostPort, method, path, headers, on_req
61
61
  if (typeof on_resp_cb === 'undefined') {
62
62
  _on_resp_cb = on_resp;
63
63
  } else {
64
- _on_resp_cb = on_req_cb;
64
+ _on_resp_cb = on_resp_cb;
65
65
  }
66
66
 
67
67
  if (typeof on_resp_data_cb === 'undefined') {
@@ -70,8 +70,14 @@ const httpRequest = ( serviceName, schemeHostPort, method, path, headers, on_req
70
70
  _on_resp_data_cb = on_resp_data_cb;
71
71
  }
72
72
 
73
- ziti.Ziti_http_request( serviceName, schemeHostPort, method, path, headers, _on_req_cb, _on_resp_cb, _on_resp_data_cb );
74
-
73
+ return new Promise((resolve, reject) => {
74
+ try {
75
+ let req = ziti.Ziti_http_request( serviceName, schemeHostPort, method, path, headers, _on_req_cb, _on_resp_cb, _on_resp_data_cb );
76
+ return resolve( req );
77
+ } catch (e) {
78
+ reject(e);
79
+ }
80
+ });
75
81
  };
76
82
 
77
83
 
package/lib/init.js CHANGED
@@ -15,19 +15,27 @@ limitations under the License.
15
15
  */
16
16
 
17
17
 
18
- const init = ( identityPath ) => {
18
+ /**
19
+ * Initialize the Ziti session and authenticate with control plane.
20
+ *
21
+ * @param {string} identityPath - File system path to the identity file.
22
+ * @param {function} [onAuthEvent] - Optional callback for authentication events.
23
+ * Called with an object containing { action, type, detail } when auth events occur.
24
+ * - action: 'login_external', 'select_external', 'cannot_continue', 'prompt_totp', 'prompt_pin'
25
+ * - type: The authentication type (e.g., 'oidc')
26
+ * - detail: Additional details (e.g., the OIDC provider URL)
27
+ * @returns {Promise<void>} Resolves when initialization is complete.
28
+ */
29
+ const init = ( identityPath, onAuthEvent ) => {
19
30
 
20
31
  return new Promise((resolve, reject) => {
21
-
22
32
  try {
23
33
  ziti.ziti_init( identityPath, ( result ) => {
24
-
25
34
  if (result instanceof Error) {
26
35
  return reject(result);
27
36
  }
28
-
29
37
  return resolve( result );
30
- });
38
+ }, onAuthEvent);
31
39
  } catch (e) {
32
40
  reject(e);
33
41
  }
@@ -0,0 +1,70 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+
18
+ /**
19
+ * Initialize external authentication with a Ziti controller.
20
+ *
21
+ * @param {string} controllerHost - The hostname of the Ziti controller (e.g., "ctrl.example.com:1280")
22
+ * @param {string} token - The external authentication token
23
+ * @returns {number} 0 on success, error code on failure
24
+ */
25
+ const initExternalAuth = ( controllerHost, token ) => {
26
+
27
+ if (typeof controllerHost !== 'string' || controllerHost.length === 0) {
28
+ throw new Error('controllerHost must be a non-empty string');
29
+ }
30
+ if (typeof token !== 'string' || token.length === 0) {
31
+ throw new Error('token must be a non-empty string');
32
+ }
33
+
34
+ return new Promise((resolve, reject) => {
35
+
36
+ try {
37
+ ziti.ziti_init_external_auth( controllerHost, async ( cfg ) => {
38
+
39
+ if (cfg instanceof Error) {
40
+ return reject(cfg);
41
+ }
42
+
43
+ function onAuthEvent(event) {
44
+
45
+ if (event.action === 'login_external') {
46
+ } else if (event.action === 'select_external') {
47
+ let ret = ziti.extAuthToken(token)
48
+ } else if (event.action === 'cannot_continue') {
49
+ } else if (event.action === 'prompt_totp') {
50
+ } else if (event.action === 'prompt_pin') {
51
+ } else {
52
+ }
53
+
54
+ }
55
+
56
+ const cfgStr = JSON.stringify(cfg)
57
+
58
+ let initResult = await ziti.init(cfgStr, onAuthEvent)
59
+
60
+ return resolve( initResult );
61
+ });
62
+ } catch (e) {
63
+ reject(e);
64
+ }
65
+
66
+ });
67
+
68
+ };
69
+
70
+ exports.initExternalAuth = initExternalAuth;
@@ -0,0 +1,31 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+
18
+ /**
19
+ * websocketClose()
20
+ *
21
+ * Close a Ziti WebSocket connection.
22
+ *
23
+ * @param {number} ws - The WebSocket handle returned from websocketConnect
24
+ * @returns {void}
25
+ */
26
+ const websocketClose = (ws) => {
27
+ ziti.ziti_websocket_close(ws);
28
+ };
29
+
30
+
31
+ exports.websocketClose = websocketClose;
@@ -0,0 +1,54 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+
18
+ /**
19
+ * Default on_connect callback
20
+ */
21
+ const defaultOnConnect = (ws) => {
22
+ console.log('websocketConnect: connected, ws:', ws);
23
+ };
24
+
25
+ /**
26
+ * Default on_data callback
27
+ */
28
+ const defaultOnData = (data) => {
29
+ console.log('websocketConnect: data received, len:', data.len);
30
+ };
31
+
32
+
33
+ /**
34
+ * websocketConnect()
35
+ *
36
+ * Connect to a Ziti service via WebSocket.
37
+ *
38
+ * @param {string} url - The WebSocket URL (e.g., 'wss://service.ziti/path')
39
+ * @param {string[]} headers - Array of headers in "name:value" format
40
+ * @param {function} on_connect_cb - Callback invoked on connection. Receives the websocket handle.
41
+ * @param {function} on_data_cb - Callback invoked when data is received. Receives {len, data}.
42
+ * @returns {void}
43
+ */
44
+ const websocketConnect = (url, headers, on_connect_cb, on_data_cb) => {
45
+
46
+ const connect_cb = (typeof on_connect_cb === 'function') ? on_connect_cb : defaultOnConnect;
47
+ const data_cb = (typeof on_data_cb === 'function') ? on_data_cb : defaultOnData;
48
+ const hdrs = Array.isArray(headers) ? headers : [];
49
+
50
+ ziti.ziti_websocket_connect(url, hdrs, connect_cb, data_cb);
51
+ };
52
+
53
+
54
+ exports.websocketConnect = websocketConnect;
@@ -0,0 +1,31 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+
18
+ /**
19
+ * websocketPing()
20
+ *
21
+ * Send a ping frame on a Ziti WebSocket connection.
22
+ *
23
+ * @param {number} ws - The WebSocket handle returned from websocketConnect
24
+ * @returns {number} 0 on success, error code on failure
25
+ */
26
+ const websocketPing = (ws) => {
27
+ return ziti.ziti_websocket_ping(ws);
28
+ };
29
+
30
+
31
+ exports.websocketPing = websocketPing;
@@ -0,0 +1,47 @@
1
+ /*
2
+ Copyright NetFoundry Inc.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+
18
+ /**
19
+ * Default on_write callback
20
+ */
21
+ const defaultOnWrite = (result) => {
22
+ console.log('websocketWrite: write completed, status:', result.status);
23
+ };
24
+
25
+
26
+ /**
27
+ * websocketWrite()
28
+ *
29
+ * Write data to a Ziti WebSocket connection.
30
+ *
31
+ * @param {number} ws - The WebSocket handle returned from websocketConnect
32
+ * @param {Buffer} data - The data to send
33
+ * @param {function} on_write_cb - Callback invoked when write completes. Receives {ws, status}.
34
+ * @returns {void}
35
+ */
36
+ const websocketWrite = (ws, data, on_write_cb) => {
37
+
38
+ const write_cb = (typeof on_write_cb === 'function') ? on_write_cb : defaultOnWrite;
39
+
40
+ // Ensure data is a Buffer
41
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
42
+
43
+ ziti.ziti_websocket_write(ws, buffer, write_cb);
44
+ };
45
+
46
+
47
+ exports.websocketWrite = websocketWrite;
package/lib/ziti.js CHANGED
@@ -161,14 +161,106 @@ exports.httpRequest = require('./httpRequest').httpRequest;
161
161
  */
162
162
  exports.httpRequestEnd = require('./httpRequestEnd').httpRequestEnd;
163
163
 
164
+ /**
165
+ * Connect to a Ziti Service via WebSocket.
166
+ * @function websocketConnect
167
+ * @param {string} url - The WebSocket URL (e.g., 'wss://service.ziti/path')
168
+ * @param {string[]} headers - Array of headers in "name:value" format
169
+ * @param {onWebSocketConnectCallback} onConnect - Callback invoked on connection.
170
+ * @param {onWebSocketDataCallback} onData - Callback invoked when data is received.
171
+ * @returns {void} No return value.
172
+ */
173
+ /**
174
+ * This callback is part of the `websocketConnect` API.
175
+ * @callback onWebSocketConnectCallback - Called when WebSocket connection is established.
176
+ * @param {number} ws - The WebSocket handle for use with websocketWrite.
177
+ * @returns {void} No return value.
178
+ */
179
+ /**
180
+ * This callback is part of the `websocketConnect` API.
181
+ * @callback onWebSocketDataCallback - Called when data is received on the WebSocket.
182
+ * @param {object} data - The received data object.
183
+ * @param {number} data.len - Length of the data (negative indicates error/close).
184
+ * @param {Buffer} data.data - The received data buffer.
185
+ * @returns {void} No return value.
186
+ */
187
+ exports.websocketConnect = require('./websocketConnect').websocketConnect;
188
+
189
+ /**
190
+ * Write data to a Ziti WebSocket connection.
191
+ * @function websocketWrite
192
+ * @param {number} ws - The WebSocket handle from websocketConnect.
193
+ * @param {Buffer} data - The data to send.
194
+ * @param {onWebSocketWriteCallback} onWrite - Callback invoked when write completes.
195
+ * @returns {void} No return value.
196
+ */
197
+ /**
198
+ * This callback is part of the `websocketWrite` API.
199
+ * @callback onWebSocketWriteCallback - Called when the write operation completes.
200
+ * @param {object} result - The write result object.
201
+ * @param {number} result.ws - The WebSocket handle.
202
+ * @param {number} result.status - Write status (0 = success, negative = error).
203
+ * @returns {void} No return value.
204
+ */
205
+ exports.websocketWrite = require('./websocketWrite').websocketWrite;
206
+
207
+ /**
208
+ * Close a Ziti WebSocket connection.
209
+ * @function websocketClose
210
+ * @param {number} ws - The WebSocket handle from websocketConnect.
211
+ * @returns {void} No return value.
212
+ */
213
+ exports.websocketClose = require('./websocketClose').websocketClose;
214
+
215
+ /**
216
+ * Send a ping frame on a Ziti WebSocket connection.
217
+ * @function websocketPing
218
+ * @param {number} ws - The WebSocket handle from websocketConnect.
219
+ * @returns {number} 0 on success, error code on failure.
220
+ */
221
+ exports.websocketPing = require('./websocketPing').websocketPing;
222
+
223
+ /**
224
+ * Provide an external JWT token for authentication.
225
+ *
226
+ * Use this function when external authentication is required (e.g., OIDC).
227
+ * The auth event callback provided to init() will indicate when external
228
+ * auth is needed along with the provider details.
229
+ *
230
+ * @function extAuthToken
231
+ * @param {string} jwtToken - The JWT token obtained from the external identity provider
232
+ * @returns {number} 0 on success, -22 (ZITI_INVALID_STATE) if context not initialized
233
+ * @throws {Error} If jwtToken is not a non-empty string
234
+ */
235
+ exports.extAuthToken = require('./extAuthToken').extAuthToken;
236
+
164
237
  /**
165
238
  * Initialize the Ziti session and authenticate with control plane.
166
239
  * @function init
167
240
  * @param {string} identityPath - File system path to the identity file.
168
- * @returns {number} A status value ranging from 0 to 255.
241
+ * @param {onAuthEventCallback} [onAuthEvent] - Optional callback for authentication events.
242
+ * @returns {Promise<void>} Resolves when initialization is complete.
243
+ */
244
+ /**
245
+ * This callback is part of the `init` API.
246
+ * @callback onAuthEventCallback - Called when authentication events occur.
247
+ * @param {object} authEvent - The authentication event object.
248
+ * @param {string} authEvent.action - The action required (e.g., 'login_external', 'select_external', 'cannot_continue', 'prompt_totp', 'prompt_pin').
249
+ * @param {string} authEvent.type - The authentication type (e.g., 'oidc').
250
+ * @param {string} authEvent.detail - Additional details (e.g., the OIDC provider URL).
251
+ * @returns {void} No return value.
169
252
  */
170
253
  exports.init = require('./init').init;
171
254
 
255
+ /**
256
+ * Initialize external authentication with a Ziti controller.
257
+ * @function initExternalAuth
258
+ * @param {string} controllerHost - The hostname of the Ziti controller (e.g., "ctrl.example.com:1280")
259
+ * @param {onAuthEventCallback} onAuthEvent - Callback for authentication events.
260
+ * @returns {number} 0 on success, error code on failure
261
+ */
262
+ exports.initExternalAuth = require('./initExternalAuth').initExternalAuth;
263
+
172
264
  // Internal use only
173
265
  exports.listen = require('./listen').listen;
174
266
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openziti/ziti-sdk-nodejs",
3
3
  "description": "A NodeJS-based SDK for delivering secure applications over a Ziti Network",
4
- "version": "0.28.1",
4
+ "version": "0.29.0",
5
5
  "main": "./lib/ziti",
6
6
  "scripts": {
7
7
  "build": "npm run build:configure && npm run build:make",
@@ -53,6 +53,7 @@
53
53
  },
54
54
  "dependencies": {
55
55
  "@mapbox/node-pre-gyp": "^2.0.3",
56
- "bindings": "^1.5.0"
56
+ "bindings": "^1.5.0",
57
+ "segfault-handler": "^1.3.0"
57
58
  }
58
59
  }
@@ -8,6 +8,7 @@ suite("Ziti SDK Addon Tests", () => {
8
8
  assert(typeof ziti.ziti_sdk_version === "function", "ziti_sdk_version should be a function");
9
9
  assert(typeof ziti.enroll === "function", "ziti_enroll should be a function");
10
10
  assert(typeof ziti.setLogger === "function", "ziti_set_logger should be a function");
11
+ assert(typeof ziti.extAuthToken === "function", "ziti_ext_auth_token should be a function");
11
12
 
12
13
  })
13
14
  test("ziti_sdk_version test", () => {