@webex/internal-plugin-encryption 3.0.0-beta.9 → 3.0.0-beta.91
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/README.md +1 -3
- package/dist/config.js +0 -9
- package/dist/config.js.map +1 -1
- package/dist/encryption.js +9 -60
- package/dist/encryption.js.map +1 -1
- package/dist/ensure-buffer.browser.js +0 -12
- package/dist/ensure-buffer.browser.js.map +1 -1
- package/dist/ensure-buffer.js +5 -12
- package/dist/ensure-buffer.js.map +1 -1
- package/dist/index.js +7 -33
- package/dist/index.js.map +1 -1
- package/dist/kms-batcher.js +6 -30
- package/dist/kms-batcher.js.map +1 -1
- package/dist/kms-certificate-validation.js +20 -88
- package/dist/kms-certificate-validation.js.map +1 -1
- package/dist/kms-dry-error-interceptor.js +1 -23
- package/dist/kms-dry-error-interceptor.js.map +1 -1
- package/dist/kms-errors.js +3 -50
- package/dist/kms-errors.js.map +1 -1
- package/dist/kms.js +74 -213
- package/dist/kms.js.map +1 -1
- package/package.json +15 -15
- package/src/config.js +3 -3
- package/src/encryption.js +66 -56
- package/src/ensure-buffer.browser.js +0 -1
- package/src/ensure-buffer.js +5 -5
- package/src/index.js +120 -96
- package/src/kms-batcher.js +50 -44
- package/src/kms-certificate-validation.js +45 -47
- package/src/kms-dry-error-interceptor.js +8 -4
- package/src/kms-errors.js +19 -16
- package/src/kms.js +210 -206
- package/test/integration/spec/encryption.js +311 -230
- package/test/integration/spec/kms.js +532 -404
- package/test/integration/spec/payload-transfom.js +69 -69
- package/test/unit/spec/encryption.js +16 -13
- package/test/unit/spec/kms-certificate-validation.js +41 -32
package/src/index.js
CHANGED
|
@@ -8,126 +8,150 @@
|
|
|
8
8
|
// by using Promise.race to resolve replays (as more requests get enqueue for a
|
|
9
9
|
// specific action, accept whichever one completes first).
|
|
10
10
|
|
|
11
|
+
import '@webex/internal-plugin-device';
|
|
12
|
+
|
|
13
|
+
import '@webex/internal-plugin-mercury';
|
|
14
|
+
|
|
11
15
|
import {registerInternalPlugin} from '@webex/webex-core';
|
|
12
16
|
import {has, isObject, isString} from 'lodash';
|
|
13
17
|
|
|
14
18
|
import Encryption from './encryption';
|
|
15
19
|
import config from './config';
|
|
16
20
|
import {DryError} from './kms-errors';
|
|
17
|
-
|
|
18
|
-
import '@webex/internal-plugin-mercury';
|
|
21
|
+
|
|
19
22
|
import KmsDryErrorInterceptor from './kms-dry-error-interceptor';
|
|
20
23
|
|
|
21
24
|
let interceptors;
|
|
22
25
|
|
|
23
26
|
if (process.env.NODE_ENV === 'test') {
|
|
24
27
|
interceptors = {
|
|
25
|
-
KmsDryErrorInterceptor: KmsDryErrorInterceptor.create
|
|
28
|
+
KmsDryErrorInterceptor: KmsDryErrorInterceptor.create,
|
|
26
29
|
};
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
registerInternalPlugin('encryption', Encryption, {
|
|
30
33
|
payloadTransformer: {
|
|
31
|
-
predicates: [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
+
},
|
|
60
76
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
+
},
|
|
69
88
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
+
},
|
|
78
98
|
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return ctx.webex.internal.encryption.kms.prepareRequest(object.kmsMessage)
|
|
99
|
-
.then((req) => {
|
|
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) => {
|
|
100
117
|
object.kmsMessage = req.wrapped;
|
|
101
118
|
});
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
.
|
|
108
|
-
object.kmsMessage
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
+
],
|
|
128
152
|
},
|
|
129
153
|
interceptors,
|
|
130
|
-
config
|
|
154
|
+
config,
|
|
131
155
|
});
|
|
132
156
|
|
|
133
157
|
export {default} from './encryption';
|
package/src/kms-batcher.js
CHANGED
|
@@ -23,14 +23,19 @@ const KmsBatcher = Batcher.extend({
|
|
|
23
23
|
processKmsMessageEvent(event) {
|
|
24
24
|
this.logger.info('kms-batcher: received kms message');
|
|
25
25
|
|
|
26
|
-
return Promise.all(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
+
);
|
|
34
39
|
},
|
|
35
40
|
|
|
36
41
|
/**
|
|
@@ -39,30 +44,34 @@ const KmsBatcher = Batcher.extend({
|
|
|
39
44
|
* @returns {Promise<Object>}
|
|
40
45
|
*/
|
|
41
46
|
prepareItem(item) {
|
|
42
|
-
return this.getDeferredForRequest(item)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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({
|
|
54
62
|
timeout,
|
|
55
|
-
request: item
|
|
56
|
-
})
|
|
57
|
-
|
|
63
|
+
request: item,
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
}, timeout);
|
|
58
67
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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));
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
|
|
73
|
+
return item;
|
|
74
|
+
});
|
|
66
75
|
},
|
|
67
76
|
|
|
68
77
|
/**
|
|
@@ -71,11 +80,10 @@ const KmsBatcher = Batcher.extend({
|
|
|
71
80
|
* @returns {Promise<Array>}
|
|
72
81
|
*/
|
|
73
82
|
prepareRequest(queue) {
|
|
74
|
-
return this.webex.internal.encryption.kms._getKMSCluster()
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}));
|
|
83
|
+
return this.webex.internal.encryption.kms._getKMSCluster().then((cluster) => ({
|
|
84
|
+
destination: cluster,
|
|
85
|
+
kmsMessages: queue.map((req) => req.wrapped),
|
|
86
|
+
}));
|
|
79
87
|
},
|
|
80
88
|
|
|
81
89
|
/**
|
|
@@ -89,7 +97,7 @@ const KmsBatcher = Batcher.extend({
|
|
|
89
97
|
method: 'POST',
|
|
90
98
|
service: 'encryption',
|
|
91
99
|
resource: '/kms/messages',
|
|
92
|
-
body: payload
|
|
100
|
+
body: payload,
|
|
93
101
|
});
|
|
94
102
|
},
|
|
95
103
|
|
|
@@ -114,10 +122,9 @@ const KmsBatcher = Batcher.extend({
|
|
|
114
122
|
* @returns {Promise}
|
|
115
123
|
*/
|
|
116
124
|
handleItemSuccess(item) {
|
|
117
|
-
return this.getDeferredForResponse(item)
|
|
118
|
-
.
|
|
119
|
-
|
|
120
|
-
});
|
|
125
|
+
return this.getDeferredForResponse(item).then((defer) => {
|
|
126
|
+
defer.resolve(item.body);
|
|
127
|
+
});
|
|
121
128
|
},
|
|
122
129
|
|
|
123
130
|
/**
|
|
@@ -126,10 +133,9 @@ const KmsBatcher = Batcher.extend({
|
|
|
126
133
|
* @returns {Promise}
|
|
127
134
|
*/
|
|
128
135
|
handleItemFailure(item, reason) {
|
|
129
|
-
return this.getDeferredForResponse(item)
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
});
|
|
136
|
+
return this.getDeferredForResponse(item).then((defer) => {
|
|
137
|
+
defer.reject(reason || new KmsError(item.body));
|
|
138
|
+
});
|
|
133
139
|
},
|
|
134
140
|
|
|
135
141
|
/**
|
|
@@ -146,7 +152,7 @@ const KmsBatcher = Batcher.extend({
|
|
|
146
152
|
*/
|
|
147
153
|
fingerprintResponse(item) {
|
|
148
154
|
return Promise.resolve(item.requestId);
|
|
149
|
-
}
|
|
155
|
+
},
|
|
150
156
|
});
|
|
151
157
|
|
|
152
158
|
export default KmsBatcher;
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
RSAPublicKey,
|
|
8
8
|
CertificateChainValidationEngine,
|
|
9
9
|
CryptoEngine,
|
|
10
|
-
setEngine
|
|
10
|
+
setEngine,
|
|
11
11
|
} from 'pkijs';
|
|
12
12
|
import {isArray} from 'lodash';
|
|
13
13
|
import jose from 'node-jose';
|
|
@@ -20,7 +20,7 @@ setEngine(
|
|
|
20
20
|
new CryptoEngine({
|
|
21
21
|
name: '',
|
|
22
22
|
crypto,
|
|
23
|
-
subtle: crypto.subtle
|
|
23
|
+
subtle: crypto.subtle,
|
|
24
24
|
})
|
|
25
25
|
);
|
|
26
26
|
|
|
@@ -83,7 +83,7 @@ const validateKtyHeader = ({kty}) => {
|
|
|
83
83
|
|
|
84
84
|
const validateKidHeader = ({kid}) => {
|
|
85
85
|
if (!isUri(kid)) {
|
|
86
|
-
throwError('
|
|
86
|
+
throwError("'kid' is not a valid URI");
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
if (parseUrl(kid).protocol !== VALID_KID_PROTOCOL) {
|
|
@@ -144,7 +144,7 @@ const validateCommonName = ([certificate], {kid}) => {
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
if (!validationSuccessful) {
|
|
147
|
-
throwError(
|
|
147
|
+
throwError("hostname of the 1st certificate does not match 'kid'");
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
150
|
|
|
@@ -158,23 +158,22 @@ const validateCommonName = ([certificate], {kid}) => {
|
|
|
158
158
|
* @throws {KMSError} if e or n doesn't match the first certificate
|
|
159
159
|
* @returns {void}
|
|
160
160
|
*/
|
|
161
|
-
const validatePublicCertificate =
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
};
|
|
161
|
+
const validatePublicCertificate = ([certificate], {e: publicExponent, n: modulus}) => {
|
|
162
|
+
const {encode} = jose.util.base64url;
|
|
163
|
+
|
|
164
|
+
const publicKey = certificate.subjectPublicKeyInfo.subjectPublicKey;
|
|
165
|
+
const asn1PublicCert = fromBER(publicKey.valueBlock.valueHex);
|
|
166
|
+
const publicCert = new RSAPublicKey({schema: asn1PublicCert.result});
|
|
167
|
+
const publicExponentHex = publicCert.publicExponent.valueBlock.valueHex;
|
|
168
|
+
const modulusHex = publicCert.modulus.valueBlock.valueHex;
|
|
169
|
+
|
|
170
|
+
if (publicExponent !== encode(publicExponentHex)) {
|
|
171
|
+
throwError('Public exponent is invalid');
|
|
172
|
+
}
|
|
173
|
+
if (modulus !== encode(modulusHex)) {
|
|
174
|
+
throwError('Modulus is invalid');
|
|
175
|
+
}
|
|
176
|
+
};
|
|
178
177
|
|
|
179
178
|
/**
|
|
180
179
|
* Validates the list of certificates against the CAs provided
|
|
@@ -187,17 +186,14 @@ const validatePublicCertificate =
|
|
|
187
186
|
const validateCertificatesSignature = (certificates, caroots = []) => {
|
|
188
187
|
const certificateEngine = new CertificateChainValidationEngine({
|
|
189
188
|
trustedCerts: caroots.map(decodeCert),
|
|
190
|
-
certs: certificates
|
|
189
|
+
certs: certificates,
|
|
191
190
|
});
|
|
192
191
|
|
|
193
|
-
return certificateEngine.verify()
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
});
|
|
192
|
+
return certificateEngine.verify().then(({result, resultCode, resultMessage}) => {
|
|
193
|
+
if (!result) {
|
|
194
|
+
throwError(`Certificate Validation failed [${resultCode}]: ${resultMessage}`);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
201
197
|
};
|
|
202
198
|
|
|
203
199
|
/**
|
|
@@ -210,25 +206,27 @@ const validateCertificatesSignature = (certificates, caroots = []) => {
|
|
|
210
206
|
* validate the KMS
|
|
211
207
|
* @returns {Promise} when resolved will return the jwt
|
|
212
208
|
*/
|
|
213
|
-
const validateKMS =
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
209
|
+
const validateKMS =
|
|
210
|
+
(caroots) =>
|
|
211
|
+
(jwt = {}) =>
|
|
212
|
+
Promise.resolve().then(() => {
|
|
213
|
+
validateKtyHeader(jwt);
|
|
214
|
+
validateKidHeader(jwt);
|
|
215
|
+
|
|
216
|
+
if (!(isArray(jwt.x5c) && jwt.x5c.length > 0)) {
|
|
217
|
+
throwError('JWK does not contain a list of certificates');
|
|
218
|
+
}
|
|
219
|
+
const certificates = jwt.x5c.map(decodeCert);
|
|
222
220
|
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
validateCommonName(certificates, jwt);
|
|
222
|
+
validatePublicCertificate(certificates, jwt);
|
|
225
223
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
// Skip validating signatures if no CA roots were provided
|
|
225
|
+
const promise = caroots
|
|
226
|
+
? validateCertificatesSignature(certificates, caroots)
|
|
227
|
+
: Promise.resolve();
|
|
229
228
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
});
|
|
229
|
+
return promise.then(() => jwt);
|
|
230
|
+
});
|
|
233
231
|
|
|
234
232
|
export default validateKMS;
|
|
@@ -24,7 +24,10 @@ export default class KmsDryErrorInterceptor extends Interceptor {
|
|
|
24
24
|
* @returns {Promise}
|
|
25
25
|
*/
|
|
26
26
|
onResponseError(options, reason) {
|
|
27
|
-
if (
|
|
27
|
+
if (
|
|
28
|
+
reason instanceof DryError &&
|
|
29
|
+
reason.message.match(/Failed to resolve authorization token in KmsMessage request for user/)
|
|
30
|
+
) {
|
|
28
31
|
this.webex.logger.error('DRY Request Failed due to kms/test-user flakiness');
|
|
29
32
|
this.webex.logger.error(reason);
|
|
30
33
|
|
|
@@ -43,13 +46,14 @@ export default class KmsDryErrorInterceptor extends Interceptor {
|
|
|
43
46
|
replay(options, reason) {
|
|
44
47
|
if (options.replayCount) {
|
|
45
48
|
options.replayCount += 1;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
49
|
+
} else {
|
|
48
50
|
options.replayCount = 1;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
if (options.replayCount > this.webex.config.maxAuthenticationReplays) {
|
|
52
|
-
this.webex.logger.error(
|
|
54
|
+
this.webex.logger.error(
|
|
55
|
+
`kms: failed after ${this.webex.config.maxAuthenticationReplays} replay attempts`
|
|
56
|
+
);
|
|
53
57
|
|
|
54
58
|
return Promise.reject(reason);
|
|
55
59
|
}
|
package/src/kms-errors.js
CHANGED
|
@@ -9,7 +9,8 @@ import {WebexHttpError} from '@webex/webex-core';
|
|
|
9
9
|
* Error class for KMS errors
|
|
10
10
|
*/
|
|
11
11
|
export class KmsError extends Exception {
|
|
12
|
-
static defaultMessage =
|
|
12
|
+
static defaultMessage =
|
|
13
|
+
'An unknown error occurred while communicating with the kms. This implies we received an error response without a body.';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* @param {HttpResponse} body
|
|
@@ -21,20 +22,20 @@ export class KmsError extends Exception {
|
|
|
21
22
|
Object.defineProperties(this, {
|
|
22
23
|
body: {
|
|
23
24
|
enumerable: false,
|
|
24
|
-
value: body
|
|
25
|
+
value: body,
|
|
25
26
|
},
|
|
26
27
|
reason: {
|
|
27
28
|
enumerable: false,
|
|
28
|
-
value: body.reason
|
|
29
|
+
value: body.reason,
|
|
29
30
|
},
|
|
30
31
|
requestId: {
|
|
31
32
|
enumerable: false,
|
|
32
|
-
value: body.requestId
|
|
33
|
+
value: body.requestId,
|
|
33
34
|
},
|
|
34
35
|
status: {
|
|
35
36
|
enumerable: false,
|
|
36
|
-
value: body.status
|
|
37
|
-
}
|
|
37
|
+
value: body.status,
|
|
38
|
+
},
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
let message = typeof body === 'string' ? body : body.reason;
|
|
@@ -63,7 +64,9 @@ export class KmsTimeoutError extends KmsError {
|
|
|
63
64
|
* @returns {string}
|
|
64
65
|
*/
|
|
65
66
|
parse({request = {}, timeout} = {}) {
|
|
66
|
-
let message = `The KMS did not respond within ${
|
|
67
|
+
let message = `The KMS did not respond within ${
|
|
68
|
+
timeout ? `${timeout} milliseconds` : 'a timely fashion'
|
|
69
|
+
}`;
|
|
67
70
|
|
|
68
71
|
if (request) {
|
|
69
72
|
if (request.method && request.uri) {
|
|
@@ -100,12 +103,12 @@ export class DryError extends WebexHttpError {
|
|
|
100
103
|
}
|
|
101
104
|
if (this.options.url) {
|
|
102
105
|
message += `\n${this.options.method} ${this.options.url}`;
|
|
103
|
-
}
|
|
104
|
-
else if (this.options.uri) {
|
|
106
|
+
} else if (this.options.uri) {
|
|
105
107
|
message += `\n${this.options.method} ${this.options.uri}`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
} else {
|
|
109
|
+
message += `\n${this.options.method} ${this.options.service.toUpperCase()}/${
|
|
110
|
+
this.options.resource
|
|
111
|
+
}`;
|
|
109
112
|
}
|
|
110
113
|
message += `\nWEBEX_TRACKING_ID: ${this.options.headers.trackingid}`;
|
|
111
114
|
|
|
@@ -119,16 +122,16 @@ export class DryError extends WebexHttpError {
|
|
|
119
122
|
Object.defineProperties(this, {
|
|
120
123
|
reason: {
|
|
121
124
|
enumerable: false,
|
|
122
|
-
value: body.reason
|
|
125
|
+
value: body.reason,
|
|
123
126
|
},
|
|
124
127
|
requestId: {
|
|
125
128
|
enumerable: false,
|
|
126
|
-
value: body.requestId
|
|
129
|
+
value: body.requestId,
|
|
127
130
|
},
|
|
128
131
|
status: {
|
|
129
132
|
enumerable: false,
|
|
130
|
-
value: body.status
|
|
131
|
-
}
|
|
133
|
+
value: body.status,
|
|
134
|
+
},
|
|
132
135
|
});
|
|
133
136
|
|
|
134
137
|
return message;
|