@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.
- package/.eslintrc.js +6 -6
- package/README.md +42 -42
- package/babel.config.js +3 -3
- package/dist/config.js +21 -21
- package/dist/config.js.map +1 -1
- package/dist/encryption.js +57 -57
- package/dist/encryption.js.map +1 -1
- package/dist/ensure-buffer.browser.js +7 -7
- package/dist/ensure-buffer.browser.js.map +1 -1
- package/dist/ensure-buffer.js +7 -7
- package/dist/ensure-buffer.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/kms-batcher.js +38 -38
- package/dist/kms-batcher.js.map +1 -1
- package/dist/kms-certificate-validation.js +50 -50
- package/dist/kms-certificate-validation.js.map +1 -1
- package/dist/kms-dry-error-interceptor.js +15 -15
- package/dist/kms-dry-error-interceptor.js.map +1 -1
- package/dist/kms-errors.js +16 -16
- package/dist/kms-errors.js.map +1 -1
- package/dist/kms.js +171 -171
- package/dist/kms.js.map +1 -1
- package/jest.config.js +3 -3
- package/package.json +20 -19
- package/process +1 -1
- package/src/config.js +50 -50
- package/src/encryption.js +257 -257
- package/src/ensure-buffer.browser.js +37 -37
- package/src/ensure-buffer.js +20 -20
- package/src/index.js +159 -159
- package/src/kms-batcher.js +158 -158
- package/src/kms-certificate-validation.js +232 -232
- package/src/kms-dry-error-interceptor.js +65 -65
- package/src/kms-errors.js +147 -147
- package/src/kms.js +848 -848
- package/test/integration/spec/encryption.js +448 -448
- package/test/integration/spec/kms.js +800 -800
- package/test/integration/spec/payload-transfom.js +97 -97
- package/test/unit/spec/encryption.js +82 -82
- package/test/unit/spec/kms-certificate-validation.js +165 -165
- 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';
|
package/src/kms-batcher.js
CHANGED
|
@@ -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;
|