@oneidentity/safeguard 7.4.0 → 8.0.0-pre36948

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/src/safeguard.js DELETED
@@ -1,937 +0,0 @@
1
- const FS = require('fs');
2
- const SIGNALR = require('@microsoft/signalr');
3
- const AXIOS = require('axios');
4
- const HTTPS = require('https');
5
- const LS = require('./LocalStorage');
6
- const SS = require('./SessionStorage');
7
- const CryptoJS = require('crypto-js');
8
-
9
- /**
10
- * SafeguardJs
11
- */
12
- const SafeguardJs = {
13
-
14
- hubConnection: SIGNALR.HubConnection,
15
-
16
- CAs: [],
17
-
18
- CAFiles: [],
19
-
20
- /**
21
- * (Public) The available services to call on a Safeguard appliance.
22
- */
23
- Services: {
24
- CORE: 'core',
25
- APPLIANCE: 'appliance',
26
- NOTIFICATION: 'notification',
27
- A2A: 'a2a'
28
- },
29
-
30
- /**
31
- * (Public) The available HTTP methods.
32
- */
33
- HttpMethods: {
34
- POST: 'post',
35
- GET: 'get',
36
- PUT: 'put',
37
- DELETE: 'delete'
38
- },
39
-
40
- /**
41
- * (Public) The available A2A credential types.
42
- */
43
- A2ATypes: {
44
- PASSWORD: 'password',
45
- PRIVATEKEY: 'privatekey'
46
- },
47
-
48
- /**
49
- * (Public) The available Ssh key formats.
50
- */
51
- SshKeyFormats: {
52
- OPENSSH: 'openssh',
53
- SSH2: 'ssh2',
54
- PUTTY: 'putty'
55
- },
56
-
57
- /**
58
- * (Internal) Saves the user token to storage.
59
- *
60
- * @param {string} data String representation of JSON object returned from the
61
- * Safeguard appliance containing the user token.
62
- */
63
- _saveUserToken: (err, data) => {
64
- if (err) {
65
- throw new Error('Failed to save user token.');
66
- }
67
-
68
- try {
69
- let obj = JSON.parse(data);
70
- if (obj.Status === 'Success') {
71
- SafeguardJs.Storage.setUserToken(obj.UserToken);
72
- } else {
73
- throw new Error('Failed to save user token.');
74
- }
75
- }
76
- catch(ex) {
77
- throw new Error('Failed to save user token.');
78
- }
79
- },
80
-
81
- /**
82
- * (Internal) Saves the access token to storage.
83
- *
84
- * @param {string} data String representation of JSON object returned from the
85
- * Safeguard appliance containing the access token.
86
- */
87
- _saveAccessToken: (err, data) => {
88
- if (err) {
89
- throw new Error('Failed to save access token.');
90
- }
91
-
92
- try {
93
- let obj = JSON.parse(data);
94
- if (obj.success) {
95
- SafeguardJs.Storage.setAccessToken(obj.access_token);
96
- } else {
97
- throw new Error('Failed to save access token.');
98
- }
99
- }
100
- catch(ex) {
101
- throw new Error('Failed to save access token.');
102
- }
103
- },
104
-
105
- /**
106
- * (Internal) Executes an HTTP request.
107
- *
108
- * @param {string} url The url of the http request.
109
- * @param {string} httpMethod The HTTP request method.
110
- * @param {string} body The body of the http request.
111
- * @param {string} type The data type of the body of the http request.
112
- * @param {Object} headers The additional headers to be added to the http request.
113
- * @param {function} callback The function to be called with the results of the http request.
114
- * @param {Object} returnData Any additional data that should be included in the callback.
115
- * @param {Object} httpsAgent (optional) An httpsAgent object. Can be used to specify certificates, as well as other ssl options.
116
- * @param {bool} getHeaders (optional) Flag for whether or not the body or headers of the response should be returned. Defaults to false.
117
- */
118
- _execute: (url, httpMethod, body, type, headers, callback, returnData, httpsAgent = null, getHeaders = false) => {
119
- if (headers) {
120
- if (!('accept' in headers)) { headers['accept'] = 'application/json'; }
121
- if (!('accept-language' in headers)) { headers['accept-language'] = 'en-US,en;q=0.9'; }
122
- if (!('content-type' in headers)) { headers['content-type'] = 'application/json'; }
123
- } else {
124
- headers = {
125
- 'accept': 'application/json',
126
- 'accept-language': 'en-US,en;q=0.9',
127
- 'content-type': 'application/json'
128
- };
129
- }
130
-
131
- let axios = null;
132
-
133
- if (httpsAgent) {
134
- axios = AXIOS({
135
- method: httpMethod,
136
- url: url,
137
- headers: headers,
138
- data: body,
139
- responseType: type,
140
- httpsAgent: httpsAgent
141
- });
142
- } else {
143
- axios = AXIOS({
144
- method: httpMethod,
145
- url: url,
146
- headers: headers,
147
- data: body,
148
- responseType: type,
149
- httpsAgent: new HTTPS.Agent({
150
- ca: SafeguardJs.CAs
151
- })
152
- });
153
- }
154
-
155
- axios
156
- .then(function (response) {
157
- let result = null;
158
- if (getHeaders) {
159
- result = JSON.stringify(response.headers);
160
- } else {
161
- result = JSON.stringify(response.data);
162
- }
163
-
164
- if (callback) {
165
- callback(null, result, returnData);
166
- }
167
- })
168
- .catch(function (error) {
169
- let result = null;
170
- if (error.response && error.response.data) {
171
- result = JSON.stringify(error.response.data);
172
- } else {
173
- result = error.message;
174
- }
175
- if (callback) {
176
- callback(new Error(result), result, returnData);
177
- }
178
- });
179
- },
180
-
181
- /**
182
- * (Internal) Executes an HTTP request and returns a promise.
183
- *
184
- * @param {string} url The url of the http request.
185
- * @param {string} httpMethod The HTTP request method.
186
- * @param {string} body The body of the http request.
187
- * @param {string} type The data type of the body of the http request.
188
- * @param {Object} headers The additional headers to be added to the http request.
189
- * @param {function} callback The function to be called with the results of the http request.
190
- * @param {Object} returnData Any additional data that should be included in the callback.
191
- * @param {Object} httpsAgent (optional) An httpsAgent object. Can be used to specify certificates, as well as other ssl options.
192
- * @param {bool} getHeaders Flag for whether or not the body or headers of the response should be returned.
193
- */
194
- _executePromise: (url, httpMethod, body, type, headers, callback, returnData, httpsAgent = null, getHeaders = false) => {
195
- return new Promise((resolve, reject) => {
196
- SafeguardJs._execute(url, httpMethod, body, type, headers, (err, data, returnData) => {
197
- if (callback) {
198
- callback(err, data, returnData);
199
- } else if (err) {
200
- reject(err);
201
- }
202
-
203
- resolve(data);
204
- }, returnData, httpsAgent, getHeaders);
205
- });
206
- },
207
-
208
- /**
209
- * (Internal) Gets the provider scope for a given provider.
210
- *
211
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
212
- * @param {string} defaultProvider (Required) The id of the default provider.
213
- * @param {string} provider (Optional) The name or id of the provider to use. Default is local.
214
- */
215
- _getProviderScope: async (hostName, defaultProvider, provider) => {
216
- if (provider == null || provider === "" || provider.toUpperCase() == "LOCAL" || provider.toUpperCase() == "CERTIFICATE") {
217
- return defaultProvider;
218
- }
219
-
220
- let results = null;
221
-
222
- try {
223
- results = await SafeguardJs._executePromise(`https://${hostName}/service/core/v4/AuthenticationProviders`, SafeguardJs.HttpMethods.GET, null, 'json', null, null, null);
224
- results = JSON.parse(results);
225
- } catch (err) {
226
- throw new Error(`Could not find the provider: '${provider}'. ${err}`);
227
- }
228
-
229
- try {
230
- for (const p of results) {
231
- if (provider.toUpperCase() == p.Name.toUpperCase()) {
232
- return p.RstsProviderScope;
233
- } else if (provider.toUpperCase() == p.RstsProviderId.toUpperCase()) {
234
- return p.RstsProviderScope;
235
- } else if (p.RstsProviderId.toUpperCase().includes(provider.toUpperCase())) {
236
- return p.RstsProviderScope;
237
- }
238
- }
239
- } catch (err) {
240
- throw new Error(`Could not find the provider: '${provider}'. ${err}`);
241
- }
242
-
243
- throw new Error(`Could not find the provider: '${provider}'`);
244
- },
245
-
246
- oAuthCodeVerifier: () => {
247
- return SafeguardJs.toBase64Url(CryptoJS.lib.WordArray.random(30));
248
- },
249
-
250
- oAuthCodeChallenge: (codeVerifier) => {
251
- return SafeguardJs.toBase64Url(CryptoJS.SHA256(codeVerifier));
252
- },
253
-
254
- toBase64Url: (data) => {
255
- return CryptoJS.enc.Base64.stringify(data).replace(/[=]/gi, '').replace(/[+]/gi, '-').replace(/[/]/gi, '_');
256
- },
257
-
258
- /**
259
- * (Internal) Gets the RSTS URL with a given redirect.
260
- *
261
- * @param {string} hostName The name or ip of the safeguard appliance.
262
- * @param {string} redirectTo The redirect URL to be used after successful authentication.
263
- */
264
- _loginUrl: (hostName, redirectTo) => {
265
- var codeVerifier = SafeguardJs.oAuthCodeVerifier();
266
- var randomState = SafeguardJs.oAuthCodeVerifier();
267
-
268
- SafeguardJs.Storage.setCodeVerifier(codeVerifier);
269
- SafeguardJs.Storage.setRandomState(randomState);
270
-
271
- return `https://${hostName}/RSTS/Login?response_type=code&code_challenge_method=S256&code_challenge=${SafeguardJs.oAuthCodeChallenge(codeVerifier)}&state=${randomState}&redirect_uri=${encodeURIComponent(redirectTo)}`;
272
- },
273
-
274
- /**
275
- * (Internal) Redirects the current window to the login page.
276
- *
277
- * @param {string} hostName The name or ip of the safeguard appliance.
278
- * @param {string} redirectTo The redirect URL to be used after successful authentication.
279
- */
280
- _goToLogin: (hostName, redirectTo) => {
281
- window.location = SafeguardJs._loginUrl(hostName, redirectTo);
282
- },
283
-
284
- /**
285
- * (Internal) Contacts the safeguard appliance to trade an access token for a user token.
286
- *
287
- * @param {string} accessToken The access token to trade.
288
- * @param {string} hostName The name or ip of the safeguard appliance.
289
- */
290
- _tradeForUserToken: (accessToken, hostName) => {
291
- let url = `https://${hostName}/service/core/v4/Token/LoginResponse`;
292
- body = {
293
- "StsAccessToken" : accessToken
294
- }
295
-
296
- return SafeguardJs._executePromise(url, SafeguardJs.HttpMethods.POST, body, 'json', null, SafeguardJs._saveUserToken);
297
- },
298
-
299
- /**
300
- * (Internal) Contacts the rsts to trade a code for an access token.
301
- *
302
- * @param {string} code The code to trade.
303
- * @param {string} codeVerifier The code verifier.
304
- * @param {string} hostName The name or ip of the safeguard appliance.
305
- */
306
- _tradeForAccessToken: (code, codeVerifier, hostName) => {
307
- let url = `https://${hostName}/RSTS/oauth2/token`;
308
- body = new URLSearchParams({
309
- grant_type: "authorization_code",
310
- code: code,
311
- code_verifier: codeVerifier
312
- });
313
- let headers = {
314
- "content-type": "application/x-www-form-urlencoded"
315
- }
316
-
317
- return SafeguardJs._executePromise(url, SafeguardJs.HttpMethods.POST, body, 'json', headers, SafeguardJs._saveAccessToken);
318
- },
319
-
320
- /**
321
- * (Internal) Opens a connection to a Safeguard appliance.
322
- *
323
- * This happens in a 3 step process:
324
- * 1. If no user token or access token is in storage, the getAccessToken function is called.
325
- * 2. If an access token is in storage, but no user token, the access token is sent to the
326
- * safeguard appliance with a request for a user token. Once a user token is secured, a
327
- * new SafeguardConnection object is returned.
328
- * 3. If a user token is in storage, a new SafeguardConnection object is returned.
329
- *
330
- * @param {string} hostName The name or ip of the safeguard appliance.
331
- * @param {function} callback The function to call with the resultant SafeguardConnection object.
332
- * @param {function} getAccessToken The function to call to acquire an access token.
333
- */
334
- _connectInternal: (hostName, callback, getAccessToken) => {
335
- if (hostName == null || hostName === "") {
336
- throw new Error('hostName may not be null or empty');
337
- }
338
-
339
- if (getAccessToken == null) {
340
- throw new Error('getAccessToken may not be null or undefined');
341
- }
342
-
343
- // If we already are connected to a host, check to see if it is the same as
344
- // what was provided. If not, this needs to be treated as a new connection.
345
- let storedHostName = SafeguardJs.Storage.getHostName();
346
- if (storedHostName && hostName !== storedHostName) {
347
- SafeguardJs.Storage.clearStorage();
348
- }
349
-
350
- SafeguardJs.Storage.setHostName(hostName);
351
-
352
- let userToken = SafeguardJs.Storage.getUserToken();
353
- let accessToken = SafeguardJs.Storage.getAccessToken();
354
- let code = SafeguardJs.Storage.getCode();
355
- let state = SafeguardJs.Storage.getState();
356
-
357
- if (userToken) {
358
- let connection = new SafeguardJs.SafeguardConnection(hostName);
359
- if (callback) {
360
- callback(connection);
361
- }
362
- return connection;
363
-
364
- } else if (accessToken) {
365
- SafeguardJs._tradeForUserToken(accessToken, hostName);
366
- let connection = new SafeguardJs.SafeguardConnection(hostName);
367
- if (callback) {
368
- callback(connection);
369
- }
370
- return connection;
371
-
372
- } else if (code && state) {
373
- let codeVerifier = SafeguardJs.Storage.getCodeVerifier();
374
- let randomState = SafeguardJs.Storage.getRandomState();
375
-
376
- SafeguardJs.Storage.clearPKCEStorage();
377
-
378
- if (state == randomState) {
379
- SafeguardJs._tradeForAccessToken(code, codeVerifier, hostName)
380
- .then(() => {
381
- accessToken = SafeguardJs.Storage.getAccessToken();
382
- SafeguardJs._tradeForUserToken(accessToken, hostName);
383
- let connection = new SafeguardJs.SafeguardConnection(hostName);
384
- if (callback) {
385
- callback(connection);
386
- }
387
- return connection;
388
- });
389
- }
390
- } else {
391
- getAccessToken();
392
- }
393
- },
394
-
395
- /**
396
- * (Public) Adds a certificate authority to the list of CAs sent with each web request.
397
- *
398
- * @param {object} ca (Required) The certificate authority to add.
399
- */
400
- addCA: (ca) => {
401
- SafeguardJs.CAs.push(ca);
402
- },
403
-
404
- /**
405
- * (Public) Adds a certificate authority to the list of CAs sent with each web request.
406
- *
407
- * @param {object} ca (Required) The path to the certificate authority file to add.
408
- */
409
- addCAFromFile: (caFile) => {
410
- try {
411
- let ca = FS.readFileSync(caFile);
412
- SafeguardJs.addCA(ca);
413
- SafeguardJs.CAFiles.push(caFile);
414
- } catch (err) {
415
- throw new Error(`Failed to add certificate authority: '${caFile}'`);
416
- }
417
- },
418
-
419
- /**
420
- * (Public) Clears the certificate authority list.
421
- *
422
- */
423
- clearCAs: () => {
424
- SafeguardJs.CAs = [];
425
- SafeguardJs.CAFiles = [];
426
- },
427
-
428
- /**
429
- * (Public) Opens a connection to a Safeguard appliance using the RSTS login page.
430
- *
431
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
432
- * @param {string} redirect (Required) The redirect URL to be used after successful authentication.
433
- * @param {function} callback (Optional) The function to call with the resultant SafeguardConnection object.
434
- * @param {SafeguardJs.Storage} storage (Optional) The storage location of any authentication information.
435
- */
436
- connectRsts: async (hostName, redirect, callback, storage) => {
437
- if (storage) {
438
- SafeguardJs.Storage = storage;
439
- } else {
440
- SafeguardJs.Storage = new SS.SessionStorage;
441
- }
442
-
443
- return SafeguardJs._connectInternal(hostName, callback, () => (SafeguardJs._goToLogin(hostName, redirect)));
444
- },
445
-
446
- /**
447
- * (Public) Opens a connection to a Safeguard appliance using a given user name and password.
448
- *
449
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
450
- * @param {string} userName (Required) The user name.
451
- * @param {string} password (Required) The password.
452
- * @param {string} provider (Optional) The name of the provider to use. Default is local.
453
- * @param {function} callback (Optional) The function to call with the resultant SafeguardConnection object.
454
- * @param {SafeguardJs.Storage} storage (Optional) The storage location of any authentication information.
455
- */
456
- connectPassword: async (hostName, userName, password, provider, callback, storage) => {
457
- if (hostName == null || hostName === "") {
458
- throw new Error('hostName may not be null or empty');
459
- }
460
-
461
- if (userName == null || userName === "") {
462
- throw new Error('userName may not be null or empty');
463
- }
464
-
465
- if (password == null || password === "") {
466
- throw new Error('password may not be null or empty');
467
- }
468
-
469
- let providerScope = await SafeguardJs._getProviderScope(hostName, 'local', provider);
470
-
471
- if (storage) {
472
- SafeguardJs.Storage = storage;
473
- } else {
474
- SafeguardJs.Storage = new LS.LocalStorage;
475
- }
476
- SafeguardJs.Storage.clearStorage();
477
- SafeguardJs.Storage.setHostName(hostName);
478
-
479
- try {
480
- let bodyData = {
481
- "grant_type" : "password",
482
- "username" : userName,
483
- "password" : password,
484
- "scope" : providerScope
485
- };
486
-
487
- let accessToken = await SafeguardJs._executePromise(`https://${hostName}/RSTS/oauth2/token`, SafeguardJs.HttpMethods.POST, bodyData, 'json', null, null, null);
488
- SafeguardJs.Storage.setAccessToken(JSON.parse(accessToken).access_token);
489
-
490
- bodyData = {
491
- "StsAccessToken" : SafeguardJs.Storage.getAccessToken()
492
- };
493
-
494
- let stsToken = await SafeguardJs._executePromise(`https://${hostName}/service/core/v4/Token/LoginResponse`, SafeguardJs.HttpMethods.POST, bodyData, 'json', null, null, null);
495
- SafeguardJs.Storage.setUserToken(JSON.parse(stsToken).UserToken);
496
-
497
- let connection = new SafeguardJs.SafeguardConnection(hostName);
498
- if (callback) {
499
- callback(connection);
500
- }
501
-
502
- return connection;
503
- } catch (err) {
504
- throw new Error(err.message);
505
- }
506
- },
507
-
508
- /**
509
- * (Public) Opens a connection to a Safeguard appliance using a given certificate.
510
- *
511
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
512
- * @param {string} cert (Required) The user certificate in pem format.
513
- * @param {string} key (Required) The user certificate's key in key format.
514
- * @param {string} pfx (Required) The user certificate in pfx format.
515
- * @param {string} passphrase (Required) The user certificate's passphrase.
516
- * @param {string} provider (Optional) The name of the provider to use. Default is local.
517
- * @param {function} callback (Optional) The function to call with the resultant SafeguardConnection object.
518
- * @param {SafeguardJs.Storage} storage (Optional) The storage location of any authentication information.
519
- */
520
- connectCertificate: async (hostName, cert, key, pfx, passphrase, provider, callback, storage) => {
521
- if (hostName == null || hostName === "") {
522
- throw new Error('hostName may not be null or empty');
523
- }
524
-
525
- if ((cert == null || cert === "") &&
526
- (key == null || key === "") &&
527
- (pfx == null || pfx === "")) {
528
- throw new Error('Either a cert and key or pfx are required.');
529
- }
530
-
531
- if (passphrase == null || passphrase === "") {
532
- throw new Error('passphrase may not be null or empty');
533
- }
534
-
535
- let providerScope = await SafeguardJs._getProviderScope(hostName, 'certificate', provider);
536
-
537
- if (storage) {
538
- SafeguardJs.Storage = storage;
539
- } else {
540
- SafeguardJs.Storage = new LS.LocalStorage;
541
- }
542
- SafeguardJs.Storage.clearStorage();
543
- SafeguardJs.Storage.setHostName(hostName);
544
-
545
- try {
546
- let bodyData = {
547
- "grant_type" : "client_credentials",
548
- "scope" : providerScope
549
- };
550
-
551
- let httpsAgent = new HTTPS.Agent({
552
- cert: cert,
553
- key: key,
554
- pfx: pfx,
555
- ca: SafeguardJs.CAs,
556
- passphrase: passphrase
557
- });
558
-
559
- let accessToken = await SafeguardJs._executePromise(`https://${hostName}/RSTS/oauth2/token`, SafeguardJs.HttpMethods.POST, bodyData, 'json', null, null, null, httpsAgent);
560
- SafeguardJs.Storage.setAccessToken(JSON.parse(accessToken).access_token);
561
-
562
- bodyData = {
563
- "StsAccessToken" : SafeguardJs.Storage.getAccessToken()
564
- };
565
-
566
- let stsToken = await SafeguardJs._executePromise(`https://${hostName}/service/core/v4/Token/LoginResponse`, SafeguardJs.HttpMethods.POST, bodyData, 'json');
567
- SafeguardJs.Storage.setUserToken(JSON.parse(stsToken).UserToken);
568
-
569
- let connection = new SafeguardJs.SafeguardConnection(hostName);
570
- if (callback) {
571
- callback(connection);
572
- }
573
-
574
- return connection;
575
- } catch (err) {
576
- throw new Error(err.message);
577
- }
578
- },
579
-
580
- /**
581
- * (Public) Opens a connection to a Safeguard appliance using a given certificate.
582
- *
583
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
584
- * @param {string} certFile (Required) The user certificate file location in pem format.
585
- * @param {string} keyFile (Required) The user certificate's key file location in key format.
586
- * @param {string} pfxFile (Required) The user certificate in pfx format.
587
- * @param {string} passphrase (Required) The user certificate's passphrase.
588
- * @param {string} provider (Optional) The name of the provider to use. Default is local.
589
- * @param {function} callback (Optional) The function to call with the resultant SafeguardConnection object.
590
- * @param {SafeguardJs.Storage} storage (Optional) The storage location of any authentication information.
591
- */
592
- connectCertificateFromFiles: async (hostName, certFile, keyFile, pfxFile, passphrase, provider, callback, storage) => {
593
- let cert = null;
594
- let key = null;
595
- let pfx = null;
596
-
597
- if (certFile) {
598
- cert = FS.readFileSync(certFile);
599
- }
600
-
601
- if (keyFile) {
602
- key = FS.readFileSync(keyFile);
603
- }
604
-
605
- if (pfxFile) {
606
- pfx = FS.readFileSync(pfxFile);
607
- }
608
-
609
- return await SafeguardJs.connectCertificate(hostName, cert, key, pfx, passphrase, provider, callback, storage);
610
- },
611
-
612
- /**
613
- * (Public) Opens a connection to a Safeguard appliance anonymously.
614
- *
615
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
616
- * @param {function} callback (Optional) The function to call with the resultant SafeguardConnection object.
617
- * @param {SafeguardJs.Storage} storage (Optional) The storage location of any authentication information.
618
- */
619
- connectAnonymous: (hostName, callback, storage) => {
620
- if (hostName == null || hostName === "") {
621
- throw new Error('hostName may not be null or empty');
622
- }
623
-
624
- if (storage) {
625
- SafeguardJs.Storage = storage;
626
- } else {
627
- SafeguardJs.Storage = new SS.SessionStorage;
628
- }
629
-
630
- SafeguardJs.Storage.clearStorage();
631
- SafeguardJs.Storage.setHostName(hostName);
632
-
633
- let connection = new SafeguardJs.SafeguardConnection(hostName);
634
- if (callback) {
635
- callback(connection);
636
- }
637
-
638
- return connection;
639
- },
640
-
641
- /**
642
- * (Public) Retrieves an application to application credential.
643
- *
644
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
645
- * @param {string} apiKey (Required) The a2a api key.
646
- * @param {string} type (Required) The type of credential to retrieve (password, privatekey, etc).
647
- * @param {string} keyFormat (Optional) The privateKeyFormat to return (openssh, ssh2, putty, etc).
648
- * @param {string} cert (Required) The user certificate in pem format.
649
- * @param {string} key (Required) The user certificate's key in key format.
650
- * @param {string} passphrase (Required) The user certificate's passphrase.
651
- * @param {function} callback (Optional) The function to call with the resultant a2a password.
652
- */
653
- a2aGetCredential: async (hostName, apiKey, type, keyFormat, cert, key, passphrase, callback) => {
654
- if (hostName == null || hostName === "") {
655
- throw new Error('hostName may not be null or empty');
656
- }
657
-
658
- if (apiKey == null || apiKey === "") {
659
- throw new Error('apiKey may not be null or empty');
660
- }
661
-
662
- if ((cert == null || cert === "") ||
663
- (key == null || key === "") ||
664
- (passphrase == null || passphrase === "")) {
665
- throw new Error('A cert and key must be specified.');
666
- }
667
-
668
- if (!keyFormat) {
669
- keyFormat = SafeguardJs.SshKeyFormats.OPENSSH;
670
- }
671
-
672
- try {
673
- let httpsAgent = new HTTPS.Agent({
674
- cert: cert,
675
- key: key,
676
- ca: SafeguardJs.CAs,
677
- passphrase: passphrase
678
- });
679
-
680
- let additionalHeaders = {
681
- 'authorization': `A2A ${apiKey}`
682
- }
683
-
684
- let credential = await SafeguardJs._executePromise(`https://${hostName}/service/a2a/v4/Credentials?type=${type}&keyFormat=${keyFormat}`, SafeguardJs.HttpMethods.GET, null, 'json', additionalHeaders, null, null, httpsAgent);
685
-
686
- // Remove any leading or trailing quotes that were added from string conversion
687
- if (credential.slice(0, 1) === '"') {
688
- credential = credential.slice(1);
689
- }
690
-
691
- if (credential.slice(-1) === '"') {
692
- credential = credential.slice(0, -1);
693
- }
694
-
695
-
696
- if (callback) {
697
- callback(credential);
698
- }
699
-
700
- return credential;
701
- } catch (err) {
702
- throw new Error(`Failed to retrieve credentials: ${err}`);
703
- }
704
- },
705
-
706
- /**
707
- * (Public) Retrieves an application to application credential.
708
- *
709
- * @param {string} hostName (Required) The name or ip of the safeguard appliance.
710
- * @param {string} apiKey (Required) The a2a api key.
711
- * @param {string} type (Required) The type of credential to retrieve (password, privatekey, etc).
712
- * @param {string} keyFormat (Optional) The privateKeyFormat to return (openssh, ssh2, putty, etc).
713
- * @param {string} certFile (Required) The user certificate file location in pem format.
714
- * @param {string} keyFile (Required) The user certificate's key file location in key format.
715
- * @param {string} passphrase (Required) The user certificate's passphrase.
716
- * @param {function} callback (Optional) The function to call with the resultant a2a password.
717
- */
718
- a2aGetCredentialFromFiles: async (hostName, apiKey, type, keyFormat, certFile, keyFile, passphrase, callback) => {
719
- let cert = null;
720
- let key = null;
721
-
722
- if (certFile) {
723
- cert = FS.readFileSync(certFile);
724
- }
725
-
726
- if (keyFile) {
727
- key = FS.readFileSync(keyFile);
728
- }
729
-
730
- return await SafeguardJs.a2aGetCredential(hostName, apiKey, type, keyFormat, cert, key, passphrase, callback);
731
- },
732
-
733
- /**
734
- *
735
- */
736
- Storage: new SS.SessionStorage,
737
-
738
- /**
739
- * (Public) Safeguard connection class for managing the connection to a given
740
- * safeguard appliance.
741
- */
742
- SafeguardConnection: class SafeguardConnection {
743
- /**
744
- * Initializes a new instance of the SafeguardConnection class.
745
- *
746
- * @param {string} hostName The host name or ip of the Safeguard appliance.
747
- */
748
- constructor(hostName) {
749
- if (hostName == null || hostName === "") {
750
- throw new Error('hostName may not be null or empty');
751
- }
752
- this.hostName = hostName;
753
- }
754
-
755
- /**
756
- * (Private) Constructs the URL for an HTTP request.
757
- *
758
- * @param {SafeguardJs.Services} service The Safeguard service the request should be sent to.
759
- * @param {string} relativeUrl The relative url of the endpoint for the HTTP request.
760
- * @param {object} paramaters An object of entries representing any parameters that
761
- * are to be added to the URL
762
- * @returns {string} The URL.
763
- */
764
- _constructUrl(service, relativeUrl, paramaters) {
765
- // Define the base URL with the given hostName
766
- let baseUrl =`https://${this.hostName}/service/`;
767
-
768
- // If any parameters are specified, add and encode them to the relative URL
769
- try {
770
- if (paramaters) {
771
- let encodeGetParams = p =>
772
- Object.entries(p).map(kv => kv.map(encodeURIComponent).join("=")).join("&");
773
-
774
- relativeUrl = `${relativeUrl}?${encodeGetParams(paramaters)}`;
775
- }
776
- } catch(ex) {
777
- throw new Error(`Could not process parameters for call to the ${service} service at endpoint ${relativeUrl}.`);
778
- }
779
-
780
- // Based on the service requested, construct the final URL
781
- switch(service) {
782
- case SafeguardJs.Services.CORE:
783
- return `${baseUrl}core/${relativeUrl}`;
784
- case SafeguardJs.Services.APPLIANCE:
785
- return `${baseUrl}appliance/${relativeUrl}`;
786
- case SafeguardJs.Services.NOTIFICATION:
787
- return `${baseUrl}notification/${relativeUrl}`;
788
- case SafeguardJs.Services.A2A:
789
- return `${baseUrl}a2a/${relativeUrl}`;
790
- default:
791
- throw new Error(`Unsupported service requested: '${service}'.`);
792
- }
793
- }
794
-
795
- /**
796
- * (Private) Creates the bearer token to be used in the authorization header.
797
- *
798
- * @returns {string} The bearer token.
799
- */
800
- _getBearerToken() {
801
- let userToken = SafeguardJs.Storage.getUserToken();
802
- if (userToken == null || userToken === "")
803
- {
804
- throw new Error('Access token is missing. Please log in again.');
805
- }
806
- return `Bearer ${userToken}`;
807
- }
808
-
809
- /**
810
- * (Public) Gets the time remaining (in seconds) of the current access token.
811
- *
812
- * @param {function} callback (Optional) The function to be called with the lifetime remaining result.
813
- */
814
- async getAccessTokenLifetimeRemaining(callback) {
815
- let bearerToken = this._getBearerToken();
816
- let url = this._constructUrl(SafeguardJs.Services.CORE, 'v4/LoginMessage', null);
817
- let additionalHeaders = {
818
- 'authorization': bearerToken,
819
- 'X-TokenLifetimeRemaining': ''
820
- }
821
- let result = await SafeguardJs._executePromise(url, SafeguardJs.HttpMethods.GET, null, 'json', additionalHeaders, null, null, null, true);
822
- result = JSON.parse(result);
823
-
824
- if (callback) {
825
- callback(result['x-tokenlifetimeremaining']);
826
- }
827
- return result['x-tokenlifetimeremaining'];
828
- }
829
-
830
- /**
831
- * (Public) Logs out a user and clears the storage of authentication information.
832
- *
833
- * @param {function} callback (Optional) The function to be called once the logout has succeeded.
834
- */
835
- async logout(callback) {
836
- let bearerToken = this._getBearerToken();
837
- let url = this._constructUrl(SafeguardJs.Services.CORE, 'v4/Token/Logout', null);
838
- let additionalHeaders = {
839
- 'authorization': bearerToken
840
- }
841
- SafeguardJs.Storage.clearStorage();
842
- let result = await SafeguardJs._executePromise(url, SafeguardJs.HttpMethods.POST, null, 'json', additionalHeaders, callback, null);
843
- return result;
844
- }
845
-
846
- /**
847
- * (Public) Invokes an HTTP request.
848
- *
849
- * @param {SafeguardJs.Services} service (Required) The Safeguard service the request should be sent to.
850
- * @param {string} httpMethod (Required) The HTTP request method.
851
- * @param {string} relativeUrl (Required) The relative url of the endpoint for the HTTP request.
852
- * @param {string} body (Optional) The body of the http request.
853
- * @param {object} paramaters (Optional) An object of entries representing any parameters that are to be added to the URL
854
- * @param {Object} additionalHeaders (Optional) The additional headers to be added to the http request.
855
- * @param {function} callback (Optional) The function to be called with the results of the http request.
856
- * @param {Object} returnData (Optional) Any additional data that should be included in the callback.
857
- */
858
- async invoke(service, httpMethod, relativeUrl, body, parameters, additionalHeaders, callback, returnData) {
859
- if (service == null || service === "") {
860
- throw new Error('service may not be null or empty');
861
- }
862
-
863
- if (httpMethod == null || httpMethod === "") {
864
- throw new Error('httpMethod may not be null or empty');
865
- }
866
-
867
- if (relativeUrl == null || relativeUrl === "") {
868
- throw new Error('relativeUrl may not be null or empty');
869
- }
870
-
871
- let userToken = SafeguardJs.Storage.getUserToken();
872
- if (userToken)
873
- {
874
- let bearerToken = this._getBearerToken();
875
- if (additionalHeaders) {
876
- additionalHeaders['authorization'] = bearerToken;
877
- } else {
878
- additionalHeaders = {
879
- 'authorization': bearerToken
880
- }
881
- }
882
- }
883
-
884
- let url = this._constructUrl(service, relativeUrl, parameters);
885
-
886
- try
887
- {
888
- let result = await SafeguardJs._executePromise(url, httpMethod, body, 'json', additionalHeaders, callback, returnData);
889
- return result;
890
- } catch (err) {
891
- throw new Error(err.message);
892
- }
893
- }
894
-
895
- /**
896
- * (Public) Registers a callback for SignalR events.
897
- *
898
- * @param {function} callback (Required) The function to be called for every SignalR event.
899
- */
900
- async registerSignalR(callback) {
901
- let userToken = SafeguardJs.Storage.getUserToken();
902
- if (userToken == null || userToken === "" || this.hostName == null || this.hostName === "") {
903
- throw new Error('You must log in before you can register for SignalR events.');
904
- }
905
-
906
- if (!callback) {
907
- throw new Error('A callback must be specified to register for SignalR events.');
908
- }
909
-
910
- // For Node.JS only: The current implementation of SignalR in javascript does not allow for specifying a client certificate in the HubConnectionBuilder.
911
- // The best way to handle this currently is to add the CA to the global https agent. This requires a file, so SignalR will currently
912
- // only be supported when the calling script has first used SafeguardJs.addCAFromFile()
913
- if (SafeguardJs.CAFiles.length != 0) {
914
- let rootCas = require('ssl-root-cas').create();
915
- for (const ca of SafeguardJs.CAFiles) {
916
- rootCas.addFile(ca);
917
- }
918
- require('https').globalAgent.options.ca.concat(rootCas);
919
- }
920
-
921
- var options = {
922
- accessTokenFactory: () => SafeguardJs.Storage.getUserToken()
923
- };
924
-
925
- SafeguardJs.hubConnection = new SIGNALR.HubConnectionBuilder()
926
- .withUrl(`https://${this.hostName}/service/event/signalr`, options)
927
- .build();
928
- SafeguardJs.hubConnection.on('NotifyEventAsync', function (ev) { if (callback) { callback(ev); } });
929
- SafeguardJs.hubConnection
930
- .start()
931
- .then(() => console.log("SignalR Started!"))
932
- .catch((error) => console.log(error));
933
- }
934
- }
935
- }
936
-
937
- module.exports = SafeguardJs;