@webex/internal-plugin-encryption 2.59.2 → 2.59.3-next.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.
Files changed (42) hide show
  1. package/.eslintrc.js +6 -6
  2. package/README.md +42 -42
  3. package/babel.config.js +3 -3
  4. package/dist/config.js +21 -21
  5. package/dist/config.js.map +1 -1
  6. package/dist/encryption.js +57 -57
  7. package/dist/encryption.js.map +1 -1
  8. package/dist/ensure-buffer.browser.js +7 -7
  9. package/dist/ensure-buffer.browser.js.map +1 -1
  10. package/dist/ensure-buffer.js +7 -7
  11. package/dist/ensure-buffer.js.map +1 -1
  12. package/dist/index.js +2 -2
  13. package/dist/index.js.map +1 -1
  14. package/dist/kms-batcher.js +38 -38
  15. package/dist/kms-batcher.js.map +1 -1
  16. package/dist/kms-certificate-validation.js +50 -50
  17. package/dist/kms-certificate-validation.js.map +1 -1
  18. package/dist/kms-dry-error-interceptor.js +15 -15
  19. package/dist/kms-dry-error-interceptor.js.map +1 -1
  20. package/dist/kms-errors.js +16 -16
  21. package/dist/kms-errors.js.map +1 -1
  22. package/dist/kms.js +171 -171
  23. package/dist/kms.js.map +1 -1
  24. package/jest.config.js +3 -3
  25. package/package.json +20 -19
  26. package/process +1 -1
  27. package/src/config.js +50 -50
  28. package/src/encryption.js +257 -257
  29. package/src/ensure-buffer.browser.js +37 -37
  30. package/src/ensure-buffer.js +20 -20
  31. package/src/index.js +159 -159
  32. package/src/kms-batcher.js +158 -158
  33. package/src/kms-certificate-validation.js +232 -232
  34. package/src/kms-dry-error-interceptor.js +65 -65
  35. package/src/kms-errors.js +147 -147
  36. package/src/kms.js +848 -848
  37. package/test/integration/spec/encryption.js +448 -448
  38. package/test/integration/spec/kms.js +800 -800
  39. package/test/integration/spec/payload-transfom.js +97 -97
  40. package/test/unit/spec/encryption.js +82 -82
  41. package/test/unit/spec/kms-certificate-validation.js +165 -165
  42. package/test/unit/spec/kms.js +103 -103
package/src/encryption.js CHANGED
@@ -1,257 +1,257 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import {EventEmitter} from 'events';
6
- import url from 'url';
7
-
8
- import {WebexPlugin} from '@webex/webex-core';
9
- import {proxyEvents, tap, transferEvents} from '@webex/common';
10
- import jose from 'node-jose';
11
- import SCR from 'node-scr';
12
-
13
- import ensureBuffer from './ensure-buffer';
14
- import KMS from './kms';
15
-
16
- const Encryption = WebexPlugin.extend({
17
- children: {
18
- kms: KMS,
19
- },
20
-
21
- namespace: 'Encryption',
22
-
23
- processKmsMessageEvent(event) {
24
- return this.kms.processKmsMessageEvent(event);
25
- },
26
-
27
- decryptBinary(scr, buffer) {
28
- return ensureBuffer(buffer).then((b) => {
29
- /* istanbul ignore if */
30
- if (buffer.length === 0 || buffer.byteLength === 0) {
31
- return Promise.reject(new Error('Attempted to decrypt zero-length buffer'));
32
- }
33
-
34
- return scr.decrypt(b);
35
- });
36
- },
37
-
38
- /**
39
- * Decrypt a SCR (Secure Content Resource) using the supplied key uri.
40
- *
41
- * @param {string} key - The uri of a key stored in KMS
42
- * @param {Object} cipherScr - An encrypted SCR
43
- * @param {Object} options
44
- * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
45
- * @returns {Object} Decrypted SCR
46
- */
47
- decryptScr(key, cipherScr, options) {
48
- return this.getKey(key, options).then((k) => SCR.fromJWE(k.jwk, cipherScr));
49
- },
50
-
51
- /**
52
- * Decrypt text using the supplied key uri.
53
- *
54
- * @param {string} key - The uri of a key stored in KMS
55
- * @param {string} ciphertext - Encrypted text
56
- * @param {Object} options
57
- * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
58
- * @returns {string} Decrypted plaintext
59
- */
60
- decryptText(key, ciphertext, options) {
61
- return this.getKey(key, options).then((k) =>
62
- jose.JWE.createDecrypt(k.jwk)
63
- .decrypt(ciphertext)
64
- .then((result) => result.plaintext.toString())
65
- );
66
- },
67
-
68
- /**
69
- * Validate and initiate a Download request for requested file
70
- *
71
- * @param {Object} scr - Plaintext
72
- * @param {Object} options - optional parameters to download a file
73
- * @returns {promise}
74
- */
75
- download(scr, options) {
76
- /* istanbul ignore if */
77
- if (!scr.loc) {
78
- return Promise.reject(new Error('`scr.loc` is required'));
79
- }
80
-
81
- const shunt = new EventEmitter();
82
- const promise = this._fetchDownloadUrl(scr, options)
83
- .then((uri) => {
84
- // eslint-disable-next-line no-shadow
85
- const options = {
86
- method: 'GET',
87
- uri,
88
- responseType: 'buffer',
89
- };
90
-
91
- const ret = this.request(options);
92
-
93
- transferEvents('progress', options.download, shunt);
94
-
95
- return ret;
96
- })
97
- .then((res) => this.decryptBinary(scr, res.body));
98
-
99
- proxyEvents(shunt, promise);
100
-
101
- return promise;
102
- },
103
-
104
- /**
105
- * Fetch Download URL for the requested file
106
- *
107
- * @param {Object} scr - Plaintext
108
- * @param {Object} options - optional parameters to download a file
109
- * @returns {promise} url of the downloadable file
110
- */
111
- _fetchDownloadUrl(scr, options) {
112
- this.logger.info('encryption: retrieving download url for encrypted file');
113
-
114
- if (process.env.NODE_ENV !== 'production' && scr.loc.includes('localhost')) {
115
- this.logger.info(
116
- 'encryption: bypassing webex files because this looks to be a test file on localhost'
117
- );
118
-
119
- return Promise.resolve(scr.loc);
120
- }
121
-
122
- const inputBody = {
123
- endpoints: [scr.loc],
124
- };
125
- const endpointUrl = url.parse(scr.loc);
126
-
127
- // hardcode the url to use 'https' and the file service '/v1/download/endpoints' api
128
- endpointUrl.protocol = 'https';
129
- endpointUrl.pathname = '/v1/download/endpoints';
130
-
131
- return this.request({
132
- method: 'POST',
133
- uri: url.format(endpointUrl),
134
- body: options
135
- ? {
136
- ...inputBody,
137
- allow: options.params.allow,
138
- }
139
- : inputBody,
140
- }).then((res) => {
141
- // eslint-disable-next-line no-shadow
142
- const url = res.body.endpoints[scr.loc];
143
-
144
- if (!url) {
145
- this.logger.warn(
146
- 'encryption: could not determine download url for `scr.loc`; attempting to download `scr.loc` directly'
147
- );
148
-
149
- return scr.loc;
150
- }
151
- this.logger.info('encryption: retrieved download url for encrypted file');
152
-
153
- return url;
154
- });
155
- },
156
-
157
- encryptBinary(file) {
158
- return ensureBuffer(file).then((buffer) =>
159
- SCR.create().then((scr) =>
160
- scr
161
- .encrypt(buffer)
162
- .then(ensureBuffer)
163
- // eslint-disable-next-line max-nested-callbacks
164
- .then((cdata) => ({scr, cdata}))
165
- )
166
- );
167
- },
168
-
169
- /**
170
- * Encrypt a SCR (Secure Content Resource) using the supplied key uri.
171
- *
172
- * @param {string} key - The uri of a key stored in KMS
173
- * @param {Object} scr - Plaintext
174
- * @param {Object} options
175
- * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
176
- * @returns {string} Encrypted SCR
177
- */
178
- encryptScr(key, scr, options) {
179
- /* istanbul ignore if */
180
- if (!scr.loc) {
181
- return Promise.reject(new Error('Cannot encrypt `scr` without first setting `loc`'));
182
- }
183
-
184
- return this.getKey(key, options).then((k) => scr.toJWE(k.jwk));
185
- },
186
-
187
- /**
188
- * Encrypt plaintext using the supplied key uri.
189
- *
190
- * @param {string} key - The uri of a key stored in KMS
191
- * @param {string} plaintext
192
- * @param {Object} options
193
- * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
194
- * @returns {string} Encrypted text
195
- */
196
- encryptText(key, plaintext, options) {
197
- return this.getKey(key, options).then((k) =>
198
- jose.JWE.createEncrypt(this.config.joseOptions, {
199
- key: k.jwk,
200
- header: {
201
- alg: 'dir',
202
- },
203
- reference: null,
204
- }).final(plaintext, 'utf8')
205
- );
206
- },
207
-
208
- /**
209
- * Fetch the key associated with the supplied KMS uri.
210
- *
211
- * @param {string} uri - The uri of a key stored in KMS
212
- * @param {Object} options
213
- * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
214
- * @returns {string} Key
215
- */
216
- getKey(uri, {onBehalfOf} = {}) {
217
- if (uri.jwk) {
218
- return this.kms.asKey(uri);
219
- }
220
-
221
- let storageKey = uri;
222
-
223
- if (onBehalfOf) {
224
- storageKey += `/onBehalfOf/${onBehalfOf}`;
225
- }
226
-
227
- return this.unboundedStorage
228
- .get(storageKey)
229
- .then((keyString) => JSON.parse(keyString))
230
- .then((keyObject) => this.kms.asKey(keyObject))
231
- .catch(() =>
232
- this.kms
233
- .fetchKey({uri, onBehalfOf})
234
- .then(tap((key) => this.unboundedStorage.put(storageKey, JSON.stringify(key, replacer))))
235
- );
236
- },
237
- });
238
-
239
- /**
240
- * JSON.stringify replacer that ensures private key data is serialized.
241
- * @param {string} k
242
- * @param {mixed} v
243
- * @returns {mixed}
244
- */
245
- function replacer(k, v) {
246
- if (k === 'jwk') {
247
- // note: this[k] and v may be different representations of the same value
248
- // eslint-disable-next-line no-invalid-this
249
- const json = this[k].toJSON(true);
250
-
251
- return json;
252
- }
253
-
254
- return v;
255
- }
256
-
257
- export default Encryption;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {EventEmitter} from 'events';
6
+ import url from 'url';
7
+
8
+ import {WebexPlugin} from '@webex/webex-core';
9
+ import {proxyEvents, tap, transferEvents} from '@webex/common';
10
+ import jose from 'node-jose';
11
+ import SCR from 'node-scr';
12
+
13
+ import ensureBuffer from './ensure-buffer';
14
+ import KMS from './kms';
15
+
16
+ const Encryption = WebexPlugin.extend({
17
+ children: {
18
+ kms: KMS,
19
+ },
20
+
21
+ namespace: 'Encryption',
22
+
23
+ processKmsMessageEvent(event) {
24
+ return this.kms.processKmsMessageEvent(event);
25
+ },
26
+
27
+ decryptBinary(scr, buffer) {
28
+ return ensureBuffer(buffer).then((b) => {
29
+ /* istanbul ignore if */
30
+ if (buffer.length === 0 || buffer.byteLength === 0) {
31
+ return Promise.reject(new Error('Attempted to decrypt zero-length buffer'));
32
+ }
33
+
34
+ return scr.decrypt(b);
35
+ });
36
+ },
37
+
38
+ /**
39
+ * Decrypt a SCR (Secure Content Resource) using the supplied key uri.
40
+ *
41
+ * @param {string} key - The uri of a key stored in KMS
42
+ * @param {Object} cipherScr - An encrypted SCR
43
+ * @param {Object} options
44
+ * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
45
+ * @returns {Object} Decrypted SCR
46
+ */
47
+ decryptScr(key, cipherScr, options) {
48
+ return this.getKey(key, options).then((k) => SCR.fromJWE(k.jwk, cipherScr));
49
+ },
50
+
51
+ /**
52
+ * Decrypt text using the supplied key uri.
53
+ *
54
+ * @param {string} key - The uri of a key stored in KMS
55
+ * @param {string} ciphertext - Encrypted text
56
+ * @param {Object} options
57
+ * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
58
+ * @returns {string} Decrypted plaintext
59
+ */
60
+ decryptText(key, ciphertext, options) {
61
+ return this.getKey(key, options).then((k) =>
62
+ jose.JWE.createDecrypt(k.jwk)
63
+ .decrypt(ciphertext)
64
+ .then((result) => result.plaintext.toString())
65
+ );
66
+ },
67
+
68
+ /**
69
+ * Validate and initiate a Download request for requested file
70
+ *
71
+ * @param {Object} scr - Plaintext
72
+ * @param {Object} options - optional parameters to download a file
73
+ * @returns {promise}
74
+ */
75
+ download(scr, options) {
76
+ /* istanbul ignore if */
77
+ if (!scr.loc) {
78
+ return Promise.reject(new Error('`scr.loc` is required'));
79
+ }
80
+
81
+ const shunt = new EventEmitter();
82
+ const promise = this._fetchDownloadUrl(scr, options)
83
+ .then((uri) => {
84
+ // eslint-disable-next-line no-shadow
85
+ const options = {
86
+ method: 'GET',
87
+ uri,
88
+ responseType: 'buffer',
89
+ };
90
+
91
+ const ret = this.request(options);
92
+
93
+ transferEvents('progress', options.download, shunt);
94
+
95
+ return ret;
96
+ })
97
+ .then((res) => this.decryptBinary(scr, res.body));
98
+
99
+ proxyEvents(shunt, promise);
100
+
101
+ return promise;
102
+ },
103
+
104
+ /**
105
+ * Fetch Download URL for the requested file
106
+ *
107
+ * @param {Object} scr - Plaintext
108
+ * @param {Object} options - optional parameters to download a file
109
+ * @returns {promise} url of the downloadable file
110
+ */
111
+ _fetchDownloadUrl(scr, options) {
112
+ this.logger.info('encryption: retrieving download url for encrypted file');
113
+
114
+ if (process.env.NODE_ENV !== 'production' && scr.loc.includes('localhost')) {
115
+ this.logger.info(
116
+ 'encryption: bypassing webex files because this looks to be a test file on localhost'
117
+ );
118
+
119
+ return Promise.resolve(scr.loc);
120
+ }
121
+
122
+ const inputBody = {
123
+ endpoints: [scr.loc],
124
+ };
125
+ const endpointUrl = url.parse(scr.loc);
126
+
127
+ // hardcode the url to use 'https' and the file service '/v1/download/endpoints' api
128
+ endpointUrl.protocol = 'https';
129
+ endpointUrl.pathname = '/v1/download/endpoints';
130
+
131
+ return this.request({
132
+ method: 'POST',
133
+ uri: url.format(endpointUrl),
134
+ body: options
135
+ ? {
136
+ ...inputBody,
137
+ allow: options.params.allow,
138
+ }
139
+ : inputBody,
140
+ }).then((res) => {
141
+ // eslint-disable-next-line no-shadow
142
+ const url = res.body.endpoints[scr.loc];
143
+
144
+ if (!url) {
145
+ this.logger.warn(
146
+ 'encryption: could not determine download url for `scr.loc`; attempting to download `scr.loc` directly'
147
+ );
148
+
149
+ return scr.loc;
150
+ }
151
+ this.logger.info('encryption: retrieved download url for encrypted file');
152
+
153
+ return url;
154
+ });
155
+ },
156
+
157
+ encryptBinary(file) {
158
+ return ensureBuffer(file).then((buffer) =>
159
+ SCR.create().then((scr) =>
160
+ scr
161
+ .encrypt(buffer)
162
+ .then(ensureBuffer)
163
+ // eslint-disable-next-line max-nested-callbacks
164
+ .then((cdata) => ({scr, cdata}))
165
+ )
166
+ );
167
+ },
168
+
169
+ /**
170
+ * Encrypt a SCR (Secure Content Resource) using the supplied key uri.
171
+ *
172
+ * @param {string} key - The uri of a key stored in KMS
173
+ * @param {Object} scr - Plaintext
174
+ * @param {Object} options
175
+ * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
176
+ * @returns {string} Encrypted SCR
177
+ */
178
+ encryptScr(key, scr, options) {
179
+ /* istanbul ignore if */
180
+ if (!scr.loc) {
181
+ return Promise.reject(new Error('Cannot encrypt `scr` without first setting `loc`'));
182
+ }
183
+
184
+ return this.getKey(key, options).then((k) => scr.toJWE(k.jwk));
185
+ },
186
+
187
+ /**
188
+ * Encrypt plaintext using the supplied key uri.
189
+ *
190
+ * @param {string} key - The uri of a key stored in KMS
191
+ * @param {string} plaintext
192
+ * @param {Object} options
193
+ * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
194
+ * @returns {string} Encrypted text
195
+ */
196
+ encryptText(key, plaintext, options) {
197
+ return this.getKey(key, options).then((k) =>
198
+ jose.JWE.createEncrypt(this.config.joseOptions, {
199
+ key: k.jwk,
200
+ header: {
201
+ alg: 'dir',
202
+ },
203
+ reference: null,
204
+ }).final(plaintext, 'utf8')
205
+ );
206
+ },
207
+
208
+ /**
209
+ * Fetch the key associated with the supplied KMS uri.
210
+ *
211
+ * @param {string} uri - The uri of a key stored in KMS
212
+ * @param {Object} options
213
+ * @param {string} options.onBehalfOf - Fetch the KMS key on behalf of another user (using the user's UUID), active user requires the 'spark.kms_orgagent' role
214
+ * @returns {string} Key
215
+ */
216
+ getKey(uri, {onBehalfOf} = {}) {
217
+ if (uri.jwk) {
218
+ return this.kms.asKey(uri);
219
+ }
220
+
221
+ let storageKey = uri;
222
+
223
+ if (onBehalfOf) {
224
+ storageKey += `/onBehalfOf/${onBehalfOf}`;
225
+ }
226
+
227
+ return this.unboundedStorage
228
+ .get(storageKey)
229
+ .then((keyString) => JSON.parse(keyString))
230
+ .then((keyObject) => this.kms.asKey(keyObject))
231
+ .catch(() =>
232
+ this.kms
233
+ .fetchKey({uri, onBehalfOf})
234
+ .then(tap((key) => this.unboundedStorage.put(storageKey, JSON.stringify(key, replacer))))
235
+ );
236
+ },
237
+ });
238
+
239
+ /**
240
+ * JSON.stringify replacer that ensures private key data is serialized.
241
+ * @param {string} k
242
+ * @param {mixed} v
243
+ * @returns {mixed}
244
+ */
245
+ function replacer(k, v) {
246
+ if (k === 'jwk') {
247
+ // note: this[k] and v may be different representations of the same value
248
+ // eslint-disable-next-line no-invalid-this
249
+ const json = this[k].toJSON(true);
250
+
251
+ return json;
252
+ }
253
+
254
+ return v;
255
+ }
256
+
257
+ export default Encryption;
@@ -1,37 +1,37 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- /* eslint-env: browser */
6
-
7
- /**
8
- * Ensures the provider buffer is, indeed, an ArrayBuffer; converts File and
9
- * Blob objects to ArrayBuffers.
10
- * @param {mixed} buffer
11
- * @returns {Promise<ArrayBuffer>}
12
- */
13
- export default function ensureBuffer(buffer) {
14
- if (buffer instanceof ArrayBuffer) {
15
- return Promise.resolve(buffer);
16
- }
17
-
18
- if (buffer.toArrayBuffer) {
19
- return Promise.resolve(buffer.toArrayBuffer());
20
- }
21
-
22
- if (buffer.buffer) {
23
- return Promise.resolve(buffer.buffer);
24
- }
25
-
26
- return new Promise((resolve, reject) => {
27
- const fr = new FileReader();
28
-
29
- fr.onload = function onload() {
30
- resolve(new Uint8Array(this.result));
31
- };
32
-
33
- fr.onerror = reject;
34
-
35
- fr.readAsArrayBuffer(buffer);
36
- });
37
- }
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ /* eslint-env: browser */
6
+
7
+ /**
8
+ * Ensures the provider buffer is, indeed, an ArrayBuffer; converts File and
9
+ * Blob objects to ArrayBuffers.
10
+ * @param {mixed} buffer
11
+ * @returns {Promise<ArrayBuffer>}
12
+ */
13
+ export default function ensureBuffer(buffer) {
14
+ if (buffer instanceof ArrayBuffer) {
15
+ return Promise.resolve(buffer);
16
+ }
17
+
18
+ if (buffer.toArrayBuffer) {
19
+ return Promise.resolve(buffer.toArrayBuffer());
20
+ }
21
+
22
+ if (buffer.buffer) {
23
+ return Promise.resolve(buffer.buffer);
24
+ }
25
+
26
+ return new Promise((resolve, reject) => {
27
+ const fr = new FileReader();
28
+
29
+ fr.onload = function onload() {
30
+ resolve(new Uint8Array(this.result));
31
+ };
32
+
33
+ fr.onerror = reject;
34
+
35
+ fr.readAsArrayBuffer(buffer);
36
+ });
37
+ }
@@ -1,20 +1,20 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import {isBuffer} from '@webex/common';
6
-
7
- /**
8
- * Ensures the provider Buffer is, indeed, a Buffer; sometimes, they seem to be
9
- * byte-arrays instead of proper Buffer objects.
10
- * @param {mixed} buffer
11
- * @returns {Promise<Buffer>}
12
- */
13
- export default function ensureBuffer(buffer) {
14
- /* istanbul ignore if */
15
- if (!isBuffer(buffer)) {
16
- return Promise.reject(new Error('`buffer` must be a buffer'));
17
- }
18
-
19
- return Promise.resolve(buffer);
20
- }
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {isBuffer} from '@webex/common';
6
+
7
+ /**
8
+ * Ensures the provider Buffer is, indeed, a Buffer; sometimes, they seem to be
9
+ * byte-arrays instead of proper Buffer objects.
10
+ * @param {mixed} buffer
11
+ * @returns {Promise<Buffer>}
12
+ */
13
+ export default function ensureBuffer(buffer) {
14
+ /* istanbul ignore if */
15
+ if (!isBuffer(buffer)) {
16
+ return Promise.reject(new Error('`buffer` must be a buffer'));
17
+ }
18
+
19
+ return Promise.resolve(buffer);
20
+ }