@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/index.js CHANGED
@@ -1,159 +1,159 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- // Note: There's a bug where if bind gets replayed because of a timeout in which
6
- // the original request eventually completed, there'll be an error indicating
7
- // the key can't be bound (because it already has been). This could be mitigated
8
- // by using Promise.race to resolve replays (as more requests get enqueue for a
9
- // specific action, accept whichever one completes first).
10
-
11
- import '@webex/internal-plugin-device';
12
-
13
- import '@webex/internal-plugin-mercury';
14
-
15
- import {registerInternalPlugin} from '@webex/webex-core';
16
- import {has, isObject, isString} from 'lodash';
17
-
18
- import Encryption from './encryption';
19
- import config from './config';
20
- import {DryError} from './kms-errors';
21
-
22
- import KmsDryErrorInterceptor from './kms-dry-error-interceptor';
23
-
24
- let interceptors;
25
-
26
- if (process.env.NODE_ENV === 'test') {
27
- interceptors = {
28
- KmsDryErrorInterceptor: KmsDryErrorInterceptor.create,
29
- };
30
- }
31
-
32
- registerInternalPlugin('encryption', Encryption, {
33
- payloadTransformer: {
34
- predicates: [
35
- {
36
- name: 'encryptKmsMessage',
37
- direction: 'outbound',
38
- // I don't see any practical way to reduce complexity here.
39
- // eslint-disable-next-line complexity
40
- test(ctx, options) {
41
- if (!has(options, 'body.kmsMessage')) {
42
- return Promise.resolve(false);
43
- }
44
-
45
- if (!isObject(options.body.kmsMessage)) {
46
- return Promise.resolve(false);
47
- }
48
-
49
- // If this is a template for a kms message, assume another transform
50
- // will fill it in later. This is a bit of a leaky abstraction, but the
51
- // alternative is building a complex rules engine for controlling
52
- // ordering of transforms
53
- if (options.body.kmsMessage.keyUris && options.body.kmsMessage.keyUris.length === 0) {
54
- return Promise.resolve(false);
55
- }
56
- if (
57
- options.body.kmsMessage.resourceUri &&
58
- (options.body.kmsMessage.resourceUri.includes('<KRO>') ||
59
- options.body.kmsMessage.resourceUri.includes('<KEYURL>'))
60
- ) {
61
- return Promise.resolve(false);
62
- }
63
- if (
64
- options.body.kmsMessage.uri &&
65
- (options.body.kmsMessage.uri.includes('<KRO>') ||
66
- options.body.kmsMessage.uri.includes('<KEYURL>'))
67
- ) {
68
- return Promise.resolve(false);
69
- }
70
-
71
- return Promise.resolve(true);
72
- },
73
- extract(options) {
74
- return Promise.resolve(options.body);
75
- },
76
- },
77
- {
78
- name: 'decryptKmsMessage',
79
- direction: 'inbound',
80
- test(ctx, response) {
81
- return Promise.resolve(
82
- has(response, 'body.kmsMessage') && isString(response.body.kmsMessage)
83
- );
84
- },
85
- extract(response) {
86
- return Promise.resolve(response.body);
87
- },
88
- },
89
- {
90
- name: 'decryptErrorResponse',
91
- direction: 'inbound',
92
- test(ctx, reason) {
93
- return Promise.resolve(Boolean(reason.body && reason.body.errorCode === 1900000));
94
- },
95
- extract(reason) {
96
- return Promise.resolve(reason);
97
- },
98
- },
99
- ],
100
- transforms: [
101
- {
102
- name: 'encryptKmsMessage',
103
- fn(ctx, object) {
104
- if (!object) {
105
- return Promise.resolve();
106
- }
107
-
108
- if (!object.kmsMessage) {
109
- return Promise.resolve();
110
- }
111
-
112
- if (isString(object.kmsMessage)) {
113
- return Promise.resolve();
114
- }
115
-
116
- return ctx.webex.internal.encryption.kms.prepareRequest(object.kmsMessage).then((req) => {
117
- object.kmsMessage = req.wrapped;
118
- });
119
- },
120
- },
121
- {
122
- name: 'decryptKmsMessage',
123
- fn(ctx, object) {
124
- return ctx.webex.internal.encryption.kms
125
- .decryptKmsMessage(object.kmsMessage)
126
- .then((kmsMessage) => {
127
- object.kmsMessage = kmsMessage;
128
- });
129
- },
130
- },
131
- {
132
- name: 'decryptErrorResponse',
133
- fn(ctx, reason) {
134
- const promises = reason.body.errors.map((error) =>
135
- ctx.webex.internal.encryption.kms.decryptKmsMessage(error.description).then((desc) => {
136
- error.description = desc;
137
- })
138
- );
139
-
140
- promises.push(
141
- ctx.webex.internal.encryption.kms
142
- .decryptKmsMessage(reason.body.message)
143
- .then((kmsMessage) => {
144
- reason.body.message = kmsMessage;
145
- })
146
- );
147
-
148
- return Promise.all(promises).then(() => Promise.reject(new DryError(reason)));
149
- },
150
- },
151
- ],
152
- },
153
- interceptors,
154
- config,
155
- });
156
-
157
- export {default} from './encryption';
158
- export {default as KMS} from './kms';
159
- export {KmsError, DryError} from './kms-errors';
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ // Note: There's a bug where if bind gets replayed because of a timeout in which
6
+ // the original request eventually completed, there'll be an error indicating
7
+ // the key can't be bound (because it already has been). This could be mitigated
8
+ // by using Promise.race to resolve replays (as more requests get enqueue for a
9
+ // specific action, accept whichever one completes first).
10
+
11
+ import '@webex/internal-plugin-device';
12
+
13
+ import '@webex/internal-plugin-mercury';
14
+
15
+ import {registerInternalPlugin} from '@webex/webex-core';
16
+ import {has, isObject, isString} from 'lodash';
17
+
18
+ import Encryption from './encryption';
19
+ import config from './config';
20
+ import {DryError} from './kms-errors';
21
+
22
+ import KmsDryErrorInterceptor from './kms-dry-error-interceptor';
23
+
24
+ let interceptors;
25
+
26
+ if (process.env.NODE_ENV === 'test') {
27
+ interceptors = {
28
+ KmsDryErrorInterceptor: KmsDryErrorInterceptor.create,
29
+ };
30
+ }
31
+
32
+ registerInternalPlugin('encryption', Encryption, {
33
+ payloadTransformer: {
34
+ predicates: [
35
+ {
36
+ name: 'encryptKmsMessage',
37
+ direction: 'outbound',
38
+ // I don't see any practical way to reduce complexity here.
39
+ // eslint-disable-next-line complexity
40
+ test(ctx, options) {
41
+ if (!has(options, 'body.kmsMessage')) {
42
+ return Promise.resolve(false);
43
+ }
44
+
45
+ if (!isObject(options.body.kmsMessage)) {
46
+ return Promise.resolve(false);
47
+ }
48
+
49
+ // If this is a template for a kms message, assume another transform
50
+ // will fill it in later. This is a bit of a leaky abstraction, but the
51
+ // alternative is building a complex rules engine for controlling
52
+ // ordering of transforms
53
+ if (options.body.kmsMessage.keyUris && options.body.kmsMessage.keyUris.length === 0) {
54
+ return Promise.resolve(false);
55
+ }
56
+ if (
57
+ options.body.kmsMessage.resourceUri &&
58
+ (options.body.kmsMessage.resourceUri.includes('<KRO>') ||
59
+ options.body.kmsMessage.resourceUri.includes('<KEYURL>'))
60
+ ) {
61
+ return Promise.resolve(false);
62
+ }
63
+ if (
64
+ options.body.kmsMessage.uri &&
65
+ (options.body.kmsMessage.uri.includes('<KRO>') ||
66
+ options.body.kmsMessage.uri.includes('<KEYURL>'))
67
+ ) {
68
+ return Promise.resolve(false);
69
+ }
70
+
71
+ return Promise.resolve(true);
72
+ },
73
+ extract(options) {
74
+ return Promise.resolve(options.body);
75
+ },
76
+ },
77
+ {
78
+ name: 'decryptKmsMessage',
79
+ direction: 'inbound',
80
+ test(ctx, response) {
81
+ return Promise.resolve(
82
+ has(response, 'body.kmsMessage') && isString(response.body.kmsMessage)
83
+ );
84
+ },
85
+ extract(response) {
86
+ return Promise.resolve(response.body);
87
+ },
88
+ },
89
+ {
90
+ name: 'decryptErrorResponse',
91
+ direction: 'inbound',
92
+ test(ctx, reason) {
93
+ return Promise.resolve(Boolean(reason.body && reason.body.errorCode === 1900000));
94
+ },
95
+ extract(reason) {
96
+ return Promise.resolve(reason);
97
+ },
98
+ },
99
+ ],
100
+ transforms: [
101
+ {
102
+ name: 'encryptKmsMessage',
103
+ fn(ctx, object) {
104
+ if (!object) {
105
+ return Promise.resolve();
106
+ }
107
+
108
+ if (!object.kmsMessage) {
109
+ return Promise.resolve();
110
+ }
111
+
112
+ if (isString(object.kmsMessage)) {
113
+ return Promise.resolve();
114
+ }
115
+
116
+ return ctx.webex.internal.encryption.kms.prepareRequest(object.kmsMessage).then((req) => {
117
+ object.kmsMessage = req.wrapped;
118
+ });
119
+ },
120
+ },
121
+ {
122
+ name: 'decryptKmsMessage',
123
+ fn(ctx, object) {
124
+ return ctx.webex.internal.encryption.kms
125
+ .decryptKmsMessage(object.kmsMessage)
126
+ .then((kmsMessage) => {
127
+ object.kmsMessage = kmsMessage;
128
+ });
129
+ },
130
+ },
131
+ {
132
+ name: 'decryptErrorResponse',
133
+ fn(ctx, reason) {
134
+ const promises = reason.body.errors.map((error) =>
135
+ ctx.webex.internal.encryption.kms.decryptKmsMessage(error.description).then((desc) => {
136
+ error.description = desc;
137
+ })
138
+ );
139
+
140
+ promises.push(
141
+ ctx.webex.internal.encryption.kms
142
+ .decryptKmsMessage(reason.body.message)
143
+ .then((kmsMessage) => {
144
+ reason.body.message = kmsMessage;
145
+ })
146
+ );
147
+
148
+ return Promise.all(promises).then(() => Promise.reject(new DryError(reason)));
149
+ },
150
+ },
151
+ ],
152
+ },
153
+ interceptors,
154
+ config,
155
+ });
156
+
157
+ export {default} from './encryption';
158
+ export {default as KMS} from './kms';
159
+ export {KmsError, DryError} from './kms-errors';
@@ -1,158 +1,158 @@
1
- /*!
2
- * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
- */
4
-
5
- import {safeSetTimeout} from '@webex/common-timers';
6
- import {Batcher} from '@webex/webex-core';
7
-
8
- import {KmsError, KmsTimeoutError} from './kms-errors';
9
-
10
- export const TIMEOUT_SYMBOL = Symbol('TIMEOUT_SYMBOL');
11
-
12
- /**
13
- * @class
14
- */
15
- const KmsBatcher = Batcher.extend({
16
- namespace: 'Encryption',
17
-
18
- /**
19
- * Accepts a kmsMessage event and passes its contents to acceptItem
20
- * @param {Object} event
21
- * @returns {Promise}
22
- */
23
- processKmsMessageEvent(event) {
24
- this.logger.info('kms-batcher: received kms message');
25
-
26
- return Promise.all(
27
- event.encryption.kmsMessages.map(
28
- (kmsMessage) =>
29
- new Promise((resolve) => {
30
- /* istanbul ignore else */
31
- if (process.env.NODE_ENV !== 'production') {
32
- this.logger.info('kms-batcher:', kmsMessage.body);
33
- }
34
-
35
- resolve(this.acceptItem(kmsMessage));
36
- })
37
- )
38
- );
39
- },
40
-
41
- /**
42
- * Attaches a timeout to the given KMS message
43
- * @param {Object} item
44
- * @returns {Promise<Object>}
45
- */
46
- prepareItem(item) {
47
- return this.getDeferredForRequest(item).then((defer) => {
48
- const timeout = item[TIMEOUT_SYMBOL];
49
-
50
- /* istanbul ignore if */
51
- if (!timeout) {
52
- throw new Error('timeout is required');
53
- }
54
-
55
- const timer = safeSetTimeout(() => {
56
- this.logger.warn(
57
- `kms: request timed out; request id: ${item.requestId}; timeout: ${timeout}`
58
- );
59
- this.handleItemFailure(
60
- item,
61
- new KmsTimeoutError({
62
- timeout,
63
- request: item,
64
- })
65
- );
66
- }, timeout);
67
-
68
- // Reminder: reassign `promise` is not a viable means of inserting into
69
- // the Promise chain
70
- defer.promise.then(() => clearTimeout(timer));
71
- defer.promise.catch(() => clearTimeout(timer));
72
-
73
- return item;
74
- });
75
- },
76
-
77
- /**
78
- * Attaches the final bits of cluster info to the payload
79
- * @param {Array} queue
80
- * @returns {Promise<Array>}
81
- */
82
- prepareRequest(queue) {
83
- return this.webex.internal.encryption.kms._getKMSCluster().then((cluster) => ({
84
- destination: cluster,
85
- kmsMessages: queue.map((req) => req.wrapped),
86
- }));
87
- },
88
-
89
- /**
90
- * @param {Object} payload
91
- * @returns {Promise<HttpResponseObject>}
92
- */
93
- submitHttpRequest(payload) {
94
- this.logger.info('kms: batched-request-length', payload.kmsMessages.length);
95
-
96
- return this.webex.request({
97
- method: 'POST',
98
- service: 'encryption',
99
- resource: '/kms/messages',
100
- body: payload,
101
- });
102
- },
103
-
104
- /**
105
- * Does nothing; the http response doesn't carry our response data
106
- * @returns {Promise}
107
- */
108
- handleHttpSuccess() {
109
- return Promise.resolve();
110
- },
111
-
112
- /**
113
- * @param {Object} item
114
- * @returns {Promise<boolean>}
115
- */
116
- didItemFail(item) {
117
- return Promise.resolve(item.status >= 400);
118
- },
119
-
120
- /**
121
- * @param {Object} item
122
- * @returns {Promise}
123
- */
124
- handleItemSuccess(item) {
125
- return this.getDeferredForResponse(item).then((defer) => {
126
- defer.resolve(item.body);
127
- });
128
- },
129
-
130
- /**
131
- * @param {Object} item
132
- * @param {KmsError} [reason]
133
- * @returns {Promise}
134
- */
135
- handleItemFailure(item, reason) {
136
- return this.getDeferredForResponse(item).then((defer) => {
137
- defer.reject(reason || new KmsError(item.body));
138
- });
139
- },
140
-
141
- /**
142
- * @param {Object} item
143
- * @returns {Promise}
144
- */
145
- fingerprintRequest(item) {
146
- return Promise.resolve(item.requestId);
147
- },
148
-
149
- /**
150
- * @param {Object} item
151
- * @returns {Promise}
152
- */
153
- fingerprintResponse(item) {
154
- return Promise.resolve(item.requestId);
155
- },
156
- });
157
-
158
- export default KmsBatcher;
1
+ /*!
2
+ * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+
5
+ import {safeSetTimeout} from '@webex/common-timers';
6
+ import {Batcher} from '@webex/webex-core';
7
+
8
+ import {KmsError, KmsTimeoutError} from './kms-errors';
9
+
10
+ export const TIMEOUT_SYMBOL = Symbol('TIMEOUT_SYMBOL');
11
+
12
+ /**
13
+ * @class
14
+ */
15
+ const KmsBatcher = Batcher.extend({
16
+ namespace: 'Encryption',
17
+
18
+ /**
19
+ * Accepts a kmsMessage event and passes its contents to acceptItem
20
+ * @param {Object} event
21
+ * @returns {Promise}
22
+ */
23
+ processKmsMessageEvent(event) {
24
+ this.logger.info('kms-batcher: received kms message');
25
+
26
+ return Promise.all(
27
+ event.encryption.kmsMessages.map(
28
+ (kmsMessage) =>
29
+ new Promise((resolve) => {
30
+ /* istanbul ignore else */
31
+ if (process.env.NODE_ENV !== 'production') {
32
+ this.logger.info('kms-batcher:', kmsMessage.body);
33
+ }
34
+
35
+ resolve(this.acceptItem(kmsMessage));
36
+ })
37
+ )
38
+ );
39
+ },
40
+
41
+ /**
42
+ * Attaches a timeout to the given KMS message
43
+ * @param {Object} item
44
+ * @returns {Promise<Object>}
45
+ */
46
+ prepareItem(item) {
47
+ return this.getDeferredForRequest(item).then((defer) => {
48
+ const timeout = item[TIMEOUT_SYMBOL];
49
+
50
+ /* istanbul ignore if */
51
+ if (!timeout) {
52
+ throw new Error('timeout is required');
53
+ }
54
+
55
+ const timer = safeSetTimeout(() => {
56
+ this.logger.warn(
57
+ `kms: request timed out; request id: ${item.requestId}; timeout: ${timeout}`
58
+ );
59
+ this.handleItemFailure(
60
+ item,
61
+ new KmsTimeoutError({
62
+ timeout,
63
+ request: item,
64
+ })
65
+ );
66
+ }, timeout);
67
+
68
+ // Reminder: reassign `promise` is not a viable means of inserting into
69
+ // the Promise chain
70
+ defer.promise.then(() => clearTimeout(timer));
71
+ defer.promise.catch(() => clearTimeout(timer));
72
+
73
+ return item;
74
+ });
75
+ },
76
+
77
+ /**
78
+ * Attaches the final bits of cluster info to the payload
79
+ * @param {Array} queue
80
+ * @returns {Promise<Array>}
81
+ */
82
+ prepareRequest(queue) {
83
+ return this.webex.internal.encryption.kms._getKMSCluster().then((cluster) => ({
84
+ destination: cluster,
85
+ kmsMessages: queue.map((req) => req.wrapped),
86
+ }));
87
+ },
88
+
89
+ /**
90
+ * @param {Object} payload
91
+ * @returns {Promise<HttpResponseObject>}
92
+ */
93
+ submitHttpRequest(payload) {
94
+ this.logger.info('kms: batched-request-length', payload.kmsMessages.length);
95
+
96
+ return this.webex.request({
97
+ method: 'POST',
98
+ service: 'encryption',
99
+ resource: '/kms/messages',
100
+ body: payload,
101
+ });
102
+ },
103
+
104
+ /**
105
+ * Does nothing; the http response doesn't carry our response data
106
+ * @returns {Promise}
107
+ */
108
+ handleHttpSuccess() {
109
+ return Promise.resolve();
110
+ },
111
+
112
+ /**
113
+ * @param {Object} item
114
+ * @returns {Promise<boolean>}
115
+ */
116
+ didItemFail(item) {
117
+ return Promise.resolve(item.status >= 400);
118
+ },
119
+
120
+ /**
121
+ * @param {Object} item
122
+ * @returns {Promise}
123
+ */
124
+ handleItemSuccess(item) {
125
+ return this.getDeferredForResponse(item).then((defer) => {
126
+ defer.resolve(item.body);
127
+ });
128
+ },
129
+
130
+ /**
131
+ * @param {Object} item
132
+ * @param {KmsError} [reason]
133
+ * @returns {Promise}
134
+ */
135
+ handleItemFailure(item, reason) {
136
+ return this.getDeferredForResponse(item).then((defer) => {
137
+ defer.reject(reason || new KmsError(item.body));
138
+ });
139
+ },
140
+
141
+ /**
142
+ * @param {Object} item
143
+ * @returns {Promise}
144
+ */
145
+ fingerprintRequest(item) {
146
+ return Promise.resolve(item.requestId);
147
+ },
148
+
149
+ /**
150
+ * @param {Object} item
151
+ * @returns {Promise}
152
+ */
153
+ fingerprintResponse(item) {
154
+ return Promise.resolve(item.requestId);
155
+ },
156
+ });
157
+
158
+ export default KmsBatcher;