@webex/internal-plugin-encryption 3.0.0-beta.21 → 3.0.0-beta.210
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/dist/encryption.js +18 -16
- package/dist/encryption.js.map +1 -1
- package/dist/kms-certificate-validation.js +4 -2
- package/dist/kms-certificate-validation.js.map +1 -1
- package/dist/kms-errors.js +6 -0
- package/dist/kms-errors.js.map +1 -1
- package/dist/kms.js +16 -7
- package/dist/kms.js.map +1 -1
- package/package.json +15 -15
- package/src/encryption.js +30 -23
- package/src/kms-certificate-validation.js +3 -3
- package/src/kms-errors.js +8 -0
- package/src/kms.js +9 -6
- package/test/integration/spec/encryption.js +2 -1
- package/test/integration/spec/kms.js +0 -1
- package/test/unit/spec/encryption.js +10 -10
- package/test/unit/spec/kms-certificate-validation.js +34 -1
- package/test/unit/spec/kms.js +103 -0
package/dist/encryption.js
CHANGED
|
@@ -73,19 +73,19 @@ var Encryption = _webexCore.WebexPlugin.extend({
|
|
|
73
73
|
},
|
|
74
74
|
/**
|
|
75
75
|
* Validate and initiate a Download request for requested file
|
|
76
|
-
*
|
|
76
|
+
* @param {Object} fileUrl - Plaintext
|
|
77
77
|
* @param {Object} scr - Plaintext
|
|
78
78
|
* @param {Object} options - optional parameters to download a file
|
|
79
79
|
* @returns {promise}
|
|
80
80
|
*/
|
|
81
|
-
download: function download(scr, options) {
|
|
81
|
+
download: function download(fileUrl, scr, options) {
|
|
82
82
|
var _this = this;
|
|
83
83
|
/* istanbul ignore if */
|
|
84
|
-
if (!scr
|
|
85
|
-
return _promise.default.reject(new Error('`scr
|
|
84
|
+
if (!fileUrl || !scr) {
|
|
85
|
+
return _promise.default.reject(new Error('`scr` and `fileUrl` are required'));
|
|
86
86
|
}
|
|
87
87
|
var shunt = new _events.EventEmitter();
|
|
88
|
-
var promise = this._fetchDownloadUrl(
|
|
88
|
+
var promise = this._fetchDownloadUrl(fileUrl, options).then(function (uri) {
|
|
89
89
|
// eslint-disable-next-line no-shadow
|
|
90
90
|
var options = {
|
|
91
91
|
method: 'GET',
|
|
@@ -103,22 +103,21 @@ var Encryption = _webexCore.WebexPlugin.extend({
|
|
|
103
103
|
},
|
|
104
104
|
/**
|
|
105
105
|
* Fetch Download URL for the requested file
|
|
106
|
-
*
|
|
107
|
-
* @param {Object} scr - Plaintext
|
|
106
|
+
* @param {Object} fileUrl - Plaintext
|
|
108
107
|
* @param {Object} options - optional parameters to download a file
|
|
109
108
|
* @returns {promise} url of the downloadable file
|
|
110
109
|
*/
|
|
111
|
-
_fetchDownloadUrl: function _fetchDownloadUrl(
|
|
110
|
+
_fetchDownloadUrl: function _fetchDownloadUrl(fileUrl, options) {
|
|
112
111
|
var _this2 = this;
|
|
113
112
|
this.logger.info('encryption: retrieving download url for encrypted file');
|
|
114
|
-
if (process.env.NODE_ENV !== 'production' &&
|
|
113
|
+
if (process.env.NODE_ENV !== 'production' && fileUrl.includes('localhost')) {
|
|
115
114
|
this.logger.info('encryption: bypassing webex files because this looks to be a test file on localhost');
|
|
116
|
-
return _promise.default.resolve(
|
|
115
|
+
return _promise.default.resolve(fileUrl);
|
|
117
116
|
}
|
|
118
117
|
var inputBody = {
|
|
119
|
-
endpoints: [
|
|
118
|
+
endpoints: [fileUrl]
|
|
120
119
|
};
|
|
121
|
-
var endpointUrl = _url.default.parse(
|
|
120
|
+
var endpointUrl = _url.default.parse(fileUrl);
|
|
122
121
|
|
|
123
122
|
// hardcode the url to use 'https' and the file service '/v1/download/endpoints' api
|
|
124
123
|
endpointUrl.protocol = 'https';
|
|
@@ -131,13 +130,16 @@ var Encryption = _webexCore.WebexPlugin.extend({
|
|
|
131
130
|
}) : inputBody
|
|
132
131
|
}).then(function (res) {
|
|
133
132
|
// eslint-disable-next-line no-shadow
|
|
134
|
-
var url = res.body.endpoints[
|
|
133
|
+
var url = res.body.endpoints[fileUrl];
|
|
135
134
|
if (!url) {
|
|
136
|
-
_this2.logger.warn('encryption: could not determine download url for `
|
|
137
|
-
return
|
|
135
|
+
_this2.logger.warn('encryption: could not determine download url for `fileUrl`; attempting to download `fileUrl` directly');
|
|
136
|
+
return fileUrl;
|
|
138
137
|
}
|
|
139
138
|
_this2.logger.info('encryption: retrieved download url for encrypted file');
|
|
140
139
|
return url;
|
|
140
|
+
}).catch(function (err) {
|
|
141
|
+
_this2.logger.warn("encryption: ".concat(err, " could not determine download url for ").concat(fileUrl, "; attempting to download ").concat(fileUrl, " directly"));
|
|
142
|
+
return fileUrl;
|
|
141
143
|
});
|
|
142
144
|
},
|
|
143
145
|
encryptBinary: function encryptBinary(file) {
|
|
@@ -225,7 +227,7 @@ var Encryption = _webexCore.WebexPlugin.extend({
|
|
|
225
227
|
}));
|
|
226
228
|
});
|
|
227
229
|
},
|
|
228
|
-
version: "3.0.0-beta.
|
|
230
|
+
version: "3.0.0-beta.210"
|
|
229
231
|
});
|
|
230
232
|
|
|
231
233
|
/**
|
package/dist/encryption.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Encryption","WebexPlugin","extend","children","kms","KMS","namespace","processKmsMessageEvent","event","decryptBinary","scr","buffer","ensureBuffer","then","b","length","byteLength","reject","Error","decrypt","decryptScr","key","cipherScr","options","getKey","k","SCR","fromJWE","jwk","decryptText","ciphertext","jose","JWE","createDecrypt","result","plaintext","toString","download","loc","shunt","EventEmitter","promise","_fetchDownloadUrl","uri","method","responseType","ret","request","transferEvents","res","body","proxyEvents","logger","info","process","env","NODE_ENV","includes","resolve","inputBody","endpoints","endpointUrl","url","parse","protocol","pathname","format","allow","params","warn","encryptBinary","file","create","encrypt","cdata","encryptScr","toJWE","encryptText","createEncrypt","config","joseOptions","header","alg","reference","final","onBehalfOf","asKey","storageKey","unboundedStorage","get","keyString","JSON","keyObject","catch","fetchKey","tap","put","replacer","v","json","toJSON"],"sources":["encryption.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {EventEmitter} from 'events';\nimport url from 'url';\n\nimport {WebexPlugin} from '@webex/webex-core';\nimport {proxyEvents, tap, transferEvents} from '@webex/common';\nimport jose from 'node-jose';\nimport SCR from 'node-scr';\n\nimport ensureBuffer from './ensure-buffer';\nimport KMS from './kms';\n\nconst Encryption = WebexPlugin.extend({\n children: {\n kms: KMS,\n },\n\n namespace: 'Encryption',\n\n processKmsMessageEvent(event) {\n return this.kms.processKmsMessageEvent(event);\n },\n\n decryptBinary(scr, buffer) {\n return ensureBuffer(buffer).then((b) => {\n /* istanbul ignore if */\n if (buffer.length === 0 || buffer.byteLength === 0) {\n return Promise.reject(new Error('Attempted to decrypt zero-length buffer'));\n }\n\n return scr.decrypt(b);\n });\n },\n\n /**\n * Decrypt a SCR (Secure Content Resource) using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {Object} cipherScr - An encrypted SCR\n * @param {Object} options\n * @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\n * @returns {Object} Decrypted SCR\n */\n decryptScr(key, cipherScr, options) {\n return this.getKey(key, options).then((k) => SCR.fromJWE(k.jwk, cipherScr));\n },\n\n /**\n * Decrypt text using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {string} ciphertext - Encrypted text\n * @param {Object} options\n * @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\n * @returns {string} Decrypted plaintext\n */\n decryptText(key, ciphertext, options) {\n return this.getKey(key, options).then((k) =>\n jose.JWE.createDecrypt(k.jwk)\n .decrypt(ciphertext)\n .then((result) => result.plaintext.toString())\n );\n },\n\n /**\n * Validate and initiate a Download request for requested file\n *\n * @param {Object} scr - Plaintext\n * @param {Object} options - optional parameters to download a file\n * @returns {promise}\n */\n download(scr, options) {\n /* istanbul ignore if */\n if (!scr.loc) {\n return Promise.reject(new Error('`scr.loc` is required'));\n }\n\n const shunt = new EventEmitter();\n const promise = this._fetchDownloadUrl(scr, options)\n .then((uri) => {\n // eslint-disable-next-line no-shadow\n const options = {\n method: 'GET',\n uri,\n responseType: 'buffer',\n };\n\n const ret = this.request(options);\n\n transferEvents('progress', options.download, shunt);\n\n return ret;\n })\n .then((res) => this.decryptBinary(scr, res.body));\n\n proxyEvents(shunt, promise);\n\n return promise;\n },\n\n /**\n * Fetch Download URL for the requested file\n *\n * @param {Object} scr - Plaintext\n * @param {Object} options - optional parameters to download a file\n * @returns {promise} url of the downloadable file\n */\n _fetchDownloadUrl(scr, options) {\n this.logger.info('encryption: retrieving download url for encrypted file');\n\n if (process.env.NODE_ENV !== 'production' && scr.loc.includes('localhost')) {\n this.logger.info(\n 'encryption: bypassing webex files because this looks to be a test file on localhost'\n );\n\n return Promise.resolve(scr.loc);\n }\n\n const inputBody = {\n endpoints: [scr.loc],\n };\n const endpointUrl = url.parse(scr.loc);\n\n // hardcode the url to use 'https' and the file service '/v1/download/endpoints' api\n endpointUrl.protocol = 'https';\n endpointUrl.pathname = '/v1/download/endpoints';\n\n return this.request({\n method: 'POST',\n uri: url.format(endpointUrl),\n body: options\n ? {\n ...inputBody,\n allow: options.params.allow,\n }\n : inputBody,\n }).then((res) => {\n // eslint-disable-next-line no-shadow\n const url = res.body.endpoints[scr.loc];\n\n if (!url) {\n this.logger.warn(\n 'encryption: could not determine download url for `scr.loc`; attempting to download `scr.loc` directly'\n );\n\n return scr.loc;\n }\n this.logger.info('encryption: retrieved download url for encrypted file');\n\n return url;\n });\n },\n\n encryptBinary(file) {\n return ensureBuffer(file).then((buffer) =>\n SCR.create().then((scr) =>\n scr\n .encrypt(buffer)\n .then(ensureBuffer)\n // eslint-disable-next-line max-nested-callbacks\n .then((cdata) => ({scr, cdata}))\n )\n );\n },\n\n /**\n * Encrypt a SCR (Secure Content Resource) using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {Object} scr - Plaintext\n * @param {Object} options\n * @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\n * @returns {string} Encrypted SCR\n */\n encryptScr(key, scr, options) {\n /* istanbul ignore if */\n if (!scr.loc) {\n return Promise.reject(new Error('Cannot encrypt `scr` without first setting `loc`'));\n }\n\n return this.getKey(key, options).then((k) => scr.toJWE(k.jwk));\n },\n\n /**\n * Encrypt plaintext using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {string} plaintext\n * @param {Object} options\n * @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\n * @returns {string} Encrypted text\n */\n encryptText(key, plaintext, options) {\n return this.getKey(key, options).then((k) =>\n jose.JWE.createEncrypt(this.config.joseOptions, {\n key: k.jwk,\n header: {\n alg: 'dir',\n },\n reference: null,\n }).final(plaintext, 'utf8')\n );\n },\n\n /**\n * Fetch the key associated with the supplied KMS uri.\n *\n * @param {string} uri - The uri of a key stored in KMS\n * @param {Object} options\n * @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\n * @returns {string} Key\n */\n getKey(uri, {onBehalfOf} = {}) {\n if (uri.jwk) {\n return this.kms.asKey(uri);\n }\n\n let storageKey = uri;\n\n if (onBehalfOf) {\n storageKey += `/onBehalfOf/${onBehalfOf}`;\n }\n\n return this.unboundedStorage\n .get(storageKey)\n .then((keyString) => JSON.parse(keyString))\n .then((keyObject) => this.kms.asKey(keyObject))\n .catch(() =>\n this.kms\n .fetchKey({uri, onBehalfOf})\n .then(tap((key) => this.unboundedStorage.put(storageKey, JSON.stringify(key, replacer))))\n );\n },\n});\n\n/**\n * JSON.stringify replacer that ensures private key data is serialized.\n * @param {string} k\n * @param {mixed} v\n * @returns {mixed}\n */\nfunction replacer(k, v) {\n if (k === 'jwk') {\n // note: this[k] and v may be different representations of the same value\n // eslint-disable-next-line no-invalid-this\n const json = this[k].toJSON(true);\n\n return json;\n }\n\n return v;\n}\n\nexport default Encryption;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["Encryption","WebexPlugin","extend","children","kms","KMS","namespace","processKmsMessageEvent","event","decryptBinary","scr","buffer","ensureBuffer","then","b","length","byteLength","reject","Error","decrypt","decryptScr","key","cipherScr","options","getKey","k","SCR","fromJWE","jwk","decryptText","ciphertext","jose","JWE","createDecrypt","result","plaintext","toString","download","fileUrl","shunt","EventEmitter","promise","_fetchDownloadUrl","uri","method","responseType","ret","request","transferEvents","res","body","proxyEvents","logger","info","process","env","NODE_ENV","includes","resolve","inputBody","endpoints","endpointUrl","url","parse","protocol","pathname","format","allow","params","warn","catch","err","encryptBinary","file","create","encrypt","cdata","encryptScr","loc","toJWE","encryptText","createEncrypt","config","joseOptions","header","alg","reference","final","onBehalfOf","asKey","storageKey","unboundedStorage","get","keyString","JSON","keyObject","fetchKey","tap","put","replacer","v","json","toJSON"],"sources":["encryption.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {EventEmitter} from 'events';\nimport url from 'url';\n\nimport {WebexPlugin} from '@webex/webex-core';\nimport {proxyEvents, tap, transferEvents} from '@webex/common';\nimport jose from 'node-jose';\nimport SCR from 'node-scr';\n\nimport ensureBuffer from './ensure-buffer';\nimport KMS from './kms';\n\nconst Encryption = WebexPlugin.extend({\n children: {\n kms: KMS,\n },\n\n namespace: 'Encryption',\n\n processKmsMessageEvent(event) {\n return this.kms.processKmsMessageEvent(event);\n },\n\n decryptBinary(scr, buffer) {\n return ensureBuffer(buffer).then((b) => {\n /* istanbul ignore if */\n if (buffer.length === 0 || buffer.byteLength === 0) {\n return Promise.reject(new Error('Attempted to decrypt zero-length buffer'));\n }\n\n return scr.decrypt(b);\n });\n },\n\n /**\n * Decrypt a SCR (Secure Content Resource) using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {Object} cipherScr - An encrypted SCR\n * @param {Object} options\n * @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\n * @returns {Object} Decrypted SCR\n */\n decryptScr(key, cipherScr, options) {\n return this.getKey(key, options).then((k) => SCR.fromJWE(k.jwk, cipherScr));\n },\n\n /**\n * Decrypt text using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {string} ciphertext - Encrypted text\n * @param {Object} options\n * @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\n * @returns {string} Decrypted plaintext\n */\n decryptText(key, ciphertext, options) {\n return this.getKey(key, options).then((k) =>\n jose.JWE.createDecrypt(k.jwk)\n .decrypt(ciphertext)\n .then((result) => result.plaintext.toString())\n );\n },\n\n /**\n * Validate and initiate a Download request for requested file\n * @param {Object} fileUrl - Plaintext\n * @param {Object} scr - Plaintext\n * @param {Object} options - optional parameters to download a file\n * @returns {promise}\n */\n download(fileUrl, scr, options) {\n /* istanbul ignore if */\n if (!fileUrl || !scr) {\n return Promise.reject(new Error('`scr` and `fileUrl` are required'));\n }\n\n const shunt = new EventEmitter();\n const promise = this._fetchDownloadUrl(fileUrl, options)\n .then((uri) => {\n // eslint-disable-next-line no-shadow\n const options = {\n method: 'GET',\n uri,\n responseType: 'buffer',\n };\n\n const ret = this.request(options);\n\n transferEvents('progress', options.download, shunt);\n\n return ret;\n })\n .then((res) => this.decryptBinary(scr, res.body));\n\n proxyEvents(shunt, promise);\n\n return promise;\n },\n\n /**\n * Fetch Download URL for the requested file\n * @param {Object} fileUrl - Plaintext\n * @param {Object} options - optional parameters to download a file\n * @returns {promise} url of the downloadable file\n */\n _fetchDownloadUrl(fileUrl, options) {\n this.logger.info('encryption: retrieving download url for encrypted file');\n\n if (process.env.NODE_ENV !== 'production' && fileUrl.includes('localhost')) {\n this.logger.info(\n 'encryption: bypassing webex files because this looks to be a test file on localhost'\n );\n\n return Promise.resolve(fileUrl);\n }\n\n const inputBody = {\n endpoints: [fileUrl],\n };\n const endpointUrl = url.parse(fileUrl);\n\n // hardcode the url to use 'https' and the file service '/v1/download/endpoints' api\n endpointUrl.protocol = 'https';\n endpointUrl.pathname = '/v1/download/endpoints';\n\n return this.request({\n method: 'POST',\n uri: url.format(endpointUrl),\n body: options\n ? {\n ...inputBody,\n allow: options.params.allow,\n }\n : inputBody,\n })\n .then((res) => {\n // eslint-disable-next-line no-shadow\n const url = res.body.endpoints[fileUrl];\n\n if (!url) {\n this.logger.warn(\n 'encryption: could not determine download url for `fileUrl`; attempting to download `fileUrl` directly'\n );\n\n return fileUrl;\n }\n this.logger.info('encryption: retrieved download url for encrypted file');\n\n return url;\n })\n .catch((err) => {\n this.logger.warn(\n `encryption: ${err} could not determine download url for ${fileUrl}; attempting to download ${fileUrl} directly`\n );\n\n return fileUrl;\n });\n },\n\n encryptBinary(file) {\n return ensureBuffer(file).then((buffer) =>\n SCR.create().then((scr) =>\n scr\n .encrypt(buffer)\n .then(ensureBuffer)\n // eslint-disable-next-line max-nested-callbacks\n .then((cdata) => ({scr, cdata}))\n )\n );\n },\n\n /**\n * Encrypt a SCR (Secure Content Resource) using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {Object} scr - Plaintext\n * @param {Object} options\n * @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\n * @returns {string} Encrypted SCR\n */\n encryptScr(key, scr, options) {\n /* istanbul ignore if */\n if (!scr.loc) {\n return Promise.reject(new Error('Cannot encrypt `scr` without first setting `loc`'));\n }\n\n return this.getKey(key, options).then((k) => scr.toJWE(k.jwk));\n },\n\n /**\n * Encrypt plaintext using the supplied key uri.\n *\n * @param {string} key - The uri of a key stored in KMS\n * @param {string} plaintext\n * @param {Object} options\n * @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\n * @returns {string} Encrypted text\n */\n encryptText(key, plaintext, options) {\n return this.getKey(key, options).then((k) =>\n jose.JWE.createEncrypt(this.config.joseOptions, {\n key: k.jwk,\n header: {\n alg: 'dir',\n },\n reference: null,\n }).final(plaintext, 'utf8')\n );\n },\n\n /**\n * Fetch the key associated with the supplied KMS uri.\n *\n * @param {string} uri - The uri of a key stored in KMS\n * @param {Object} options\n * @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\n * @returns {string} Key\n */\n getKey(uri, {onBehalfOf} = {}) {\n if (uri.jwk) {\n return this.kms.asKey(uri);\n }\n\n let storageKey = uri;\n\n if (onBehalfOf) {\n storageKey += `/onBehalfOf/${onBehalfOf}`;\n }\n\n return this.unboundedStorage\n .get(storageKey)\n .then((keyString) => JSON.parse(keyString))\n .then((keyObject) => this.kms.asKey(keyObject))\n .catch(() =>\n this.kms\n .fetchKey({uri, onBehalfOf})\n .then(tap((key) => this.unboundedStorage.put(storageKey, JSON.stringify(key, replacer))))\n );\n },\n});\n\n/**\n * JSON.stringify replacer that ensures private key data is serialized.\n * @param {string} k\n * @param {mixed} v\n * @returns {mixed}\n */\nfunction replacer(k, v) {\n if (k === 'jwk') {\n // note: this[k] and v may be different representations of the same value\n // eslint-disable-next-line no-invalid-this\n const json = this[k].toJSON(true);\n\n return json;\n }\n\n return v;\n}\n\nexport default Encryption;\n"],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequ
|
|
|
10
10
|
_Object$defineProperty(exports, "__esModule", {
|
|
11
11
|
value: true
|
|
12
12
|
});
|
|
13
|
-
exports.default = exports.KMSError = void 0;
|
|
13
|
+
exports.validateCommonName = exports.default = exports.X509_SUBJECT_ALT_NAME_KEY = exports.KMSError = void 0;
|
|
14
14
|
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
|
|
15
15
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray"));
|
|
16
16
|
var _createClass2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/createClass"));
|
|
@@ -46,6 +46,7 @@ var X509_SUBJECT_ALT_NAME_KEY = '2.5.29.17';
|
|
|
46
46
|
* Customize Error so the SDK knows to quit retrying and notify
|
|
47
47
|
* the user
|
|
48
48
|
*/
|
|
49
|
+
exports.X509_SUBJECT_ALT_NAME_KEY = X509_SUBJECT_ALT_NAME_KEY;
|
|
49
50
|
var KMSError = /*#__PURE__*/function (_Error) {
|
|
50
51
|
(0, _inherits2.default)(KMSError, _Error);
|
|
51
52
|
var _super = _createSuper(KMSError);
|
|
@@ -137,7 +138,7 @@ var validateCommonName = function validateCommonName(_ref3, _ref4) {
|
|
|
137
138
|
try {
|
|
138
139
|
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
139
140
|
var entry = _step2.value;
|
|
140
|
-
var san = entry.value;
|
|
141
|
+
var san = entry.value.toLowerCase();
|
|
141
142
|
validationSuccessful = san === kidHostname;
|
|
142
143
|
if (validationSuccessful) {
|
|
143
144
|
break;
|
|
@@ -196,6 +197,7 @@ var validateCommonName = function validateCommonName(_ref3, _ref4) {
|
|
|
196
197
|
* @throws {KMSError} if e or n doesn't match the first certificate
|
|
197
198
|
* @returns {void}
|
|
198
199
|
*/
|
|
200
|
+
exports.validateCommonName = validateCommonName;
|
|
199
201
|
var validatePublicCertificate = function validatePublicCertificate(_ref6, _ref7) {
|
|
200
202
|
var _ref8 = (0, _slicedToArray2.default)(_ref6, 1),
|
|
201
203
|
certificate = _ref8[0];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["setEngine","crypto","CryptoEngine","name","subtle","VALID_KTY","VALID_KID_PROTOCOL","X509_COMMON_NAME_KEY","X509_SUBJECT_ALT_NAME_KEY","KMSError","message","kmsError","Error","throwError","err","decodeCert","pem","der","Buffer","from","ber","Uint8Array","buffer","asn1","fromBER","Certificate","schema","result","validateKtyHeader","kty","validateKidHeader","kid","isUri","parseUrl","protocol","validateCommonName","certificate","kidHostname","hostname","validationSuccessful","extensions","extension","extnID","altNames","parsedValue","entry","san","value","subjectAttributes","subject","typesAndValues","attribute","type","commonName","valueBlock","validatePublicCertificate","publicExponent","e","modulus","n","encode","jose","util","base64url","publicKey","subjectPublicKeyInfo","subjectPublicKey","asn1PublicCert","valueHex","publicCert","RSAPublicKey","publicExponentHex","modulusHex","validateCertificatesSignature","certificates","caroots","certificateEngine","CertificateChainValidationEngine","trustedCerts","map","certs","verify","then","resultCode","resultMessage","validateKMS","jwt","resolve","x5c","length","promise"],"sources":["kms-certificate-validation.js"],"sourcesContent":["import {parse as parseUrl} from 'url';\n\nimport {isUri} from 'valid-url';\nimport {fromBER} from 'asn1js';\nimport {\n Certificate,\n RSAPublicKey,\n CertificateChainValidationEngine,\n CryptoEngine,\n setEngine,\n} from 'pkijs';\nimport {isArray} from 'lodash';\nimport jose from 'node-jose';\nimport crypto from 'isomorphic-webcrypto';\nimport {Buffer} from 'safe-buffer';\n\nsetEngine(\n 'newEngine',\n crypto,\n new CryptoEngine({\n name: '',\n crypto,\n subtle: crypto.subtle,\n })\n);\n\nconst VALID_KTY = 'RSA';\nconst VALID_KID_PROTOCOL = 'kms:';\n\nconst X509_COMMON_NAME_KEY = '2.5.4.3';\n\nconst X509_SUBJECT_ALT_NAME_KEY = '2.5.29.17';\n\n/**\n * Customize Error so the SDK knows to quit retrying and notify\n * the user\n */\nexport class KMSError extends Error {\n /**\n * add kmsError field to notify\n * @param {string} message\n */\n constructor(message) {\n super(message);\n this.kmsError = true;\n }\n}\n\nconst throwError = (err) => {\n throw new KMSError(`INVALID KMS: ${err}`);\n};\n\n/**\n * Converts the PEM string to a pkijs certificate object\n * @param {string} pem PEM representation of a certificate\n * @returns {Certificate} pkijs object of the certificate\n */\nconst decodeCert = (pem) => {\n if (typeof pem !== 'string') {\n throwError('certificate needs to be a string');\n }\n\n const der = Buffer.from(pem, 'base64');\n const ber = new Uint8Array(der).buffer;\n\n const asn1 = fromBER(ber);\n\n return new Certificate({schema: asn1.result});\n};\n\n/**\n * Validate the 'kty' property of the KMS credentials\n * @param {Object} JWT KMS credentials\n * @param {string} JWT.kty type of certificate\n * @throws {KMSError} if kty is not a valid type\n * @returns {void}\n */\nconst validateKtyHeader = ({kty}) => {\n if (kty !== VALID_KTY) {\n throwError(`'kty' header must be '${VALID_KTY}'`);\n }\n};\n\nconst validateKidHeader = ({kid}) => {\n if (!isUri(kid)) {\n throwError(\"'kid' is not a valid URI\");\n }\n\n if (parseUrl(kid).protocol !== VALID_KID_PROTOCOL) {\n throwError(`'kid' protocol must be '${VALID_KID_PROTOCOL}'`);\n }\n};\n\n/**\n * Checks the first certificate matches the 'kid' in the JWT.\n * It first checks the Subject Alternative Name then it checks\n * the Common Name\n * @param {Certificate} certificate represents the KMS\n * @param {Object} JWT KMS credentials\n * @param {string} JWT.kid the uri of the KMS\n * @throws {KMSError} if unable to validate certificate against KMS credentials\n * @returns {void}\n */\nconst validateCommonName = ([certificate], {kid}) => {\n const kidHostname = parseUrl(kid).hostname;\n let validationSuccessful = false;\n\n if (certificate.extensions) {\n // Subject Alt Names are in here\n for (const extension of certificate.extensions) {\n if (extension.extnID === X509_SUBJECT_ALT_NAME_KEY) {\n const {altNames} = extension.parsedValue;\n\n for (const entry of altNames) {\n const san = entry.value;\n\n validationSuccessful = san === kidHostname;\n if (validationSuccessful) {\n break;\n }\n }\n\n if (validationSuccessful) {\n break;\n }\n }\n }\n }\n\n if (!validationSuccessful) {\n // Didn't match kid in the Subject Alt Names, checking the Common Name\n const subjectAttributes = certificate.subject.typesAndValues;\n\n for (const attribute of subjectAttributes) {\n if (attribute.type === X509_COMMON_NAME_KEY) {\n const commonName = attribute.value.valueBlock.value;\n\n validationSuccessful = commonName === kidHostname;\n if (validationSuccessful) {\n break;\n }\n }\n }\n }\n\n if (!validationSuccessful) {\n throwError(\"hostname of the 1st certificate does not match 'kid'\");\n }\n};\n\n/**\n * Validate the first KMS certificate against the information\n * provided in the JWT\n * @param {Certificate} certificate first certificate the identifies the KMS\n * @param {Object} JWT credentials of the KMS\n * @param {string} JWT.e Public exponent of the first certificate\n * @param {string} KWT.n Modulus of the first certificate\n * @throws {KMSError} if e or n doesn't match the first certificate\n * @returns {void}\n */\nconst validatePublicCertificate = ([certificate], {e: publicExponent, n: modulus}) => {\n const {encode} = jose.util.base64url;\n\n const publicKey = certificate.subjectPublicKeyInfo.subjectPublicKey;\n const asn1PublicCert = fromBER(publicKey.valueBlock.valueHex);\n const publicCert = new RSAPublicKey({schema: asn1PublicCert.result});\n const publicExponentHex = publicCert.publicExponent.valueBlock.valueHex;\n const modulusHex = publicCert.modulus.valueBlock.valueHex;\n\n if (publicExponent !== encode(publicExponentHex)) {\n throwError('Public exponent is invalid');\n }\n if (modulus !== encode(modulusHex)) {\n throwError('Modulus is invalid');\n }\n};\n\n/**\n * Validates the list of certificates against the CAs provided\n * @param {certificate[]} certificates list of certificates provided\n * by the KMS to certify itself\n * @param {string[]} [caroots=[]] list of Certificate Authorities used to\n * validate the KMS's certificates\n * @returns {Promise} rejects if unable to validate the certificates\n */\nconst validateCertificatesSignature = (certificates, caroots = []) => {\n const certificateEngine = new CertificateChainValidationEngine({\n trustedCerts: caroots.map(decodeCert),\n certs: certificates,\n });\n\n return certificateEngine.verify().then(({result, resultCode, resultMessage}) => {\n if (!result) {\n throwError(`Certificate Validation failed [${resultCode}]: ${resultMessage}`);\n }\n });\n};\n\n/**\n * Validates the information provided by the KMS. This is a curried function.\n * The first function takes the caroots param and returns a second function.\n * The second function takes the credentials of the KMS and validates it\n * @param {string[]} caroots PEM encoded certificates that will be used\n * as Certificate Authorities\n * @param {Object} jwt Object containing the fields necessary to\n * validate the KMS\n * @returns {Promise} when resolved will return the jwt\n */\nconst validateKMS =\n (caroots) =>\n (jwt = {}) =>\n Promise.resolve().then(() => {\n validateKtyHeader(jwt);\n validateKidHeader(jwt);\n\n if (!(isArray(jwt.x5c) && jwt.x5c.length > 0)) {\n throwError('JWK does not contain a list of certificates');\n }\n const certificates = jwt.x5c.map(decodeCert);\n\n validateCommonName(certificates, jwt);\n validatePublicCertificate(certificates, jwt);\n\n // Skip validating signatures if no CA roots were provided\n const promise = caroots\n ? validateCertificatesSignature(certificates, caroots)\n : Promise.resolve();\n\n return promise.then(() => jwt);\n });\n\nexport default validateKMS;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["setEngine","crypto","CryptoEngine","name","subtle","VALID_KTY","VALID_KID_PROTOCOL","X509_COMMON_NAME_KEY","X509_SUBJECT_ALT_NAME_KEY","KMSError","message","kmsError","Error","throwError","err","decodeCert","pem","der","Buffer","from","ber","Uint8Array","buffer","asn1","fromBER","Certificate","schema","result","validateKtyHeader","kty","validateKidHeader","kid","isUri","parseUrl","protocol","validateCommonName","certificate","kidHostname","hostname","validationSuccessful","extensions","extension","extnID","altNames","parsedValue","entry","san","value","toLowerCase","subjectAttributes","subject","typesAndValues","attribute","type","commonName","valueBlock","validatePublicCertificate","publicExponent","e","modulus","n","encode","jose","util","base64url","publicKey","subjectPublicKeyInfo","subjectPublicKey","asn1PublicCert","valueHex","publicCert","RSAPublicKey","publicExponentHex","modulusHex","validateCertificatesSignature","certificates","caroots","certificateEngine","CertificateChainValidationEngine","trustedCerts","map","certs","verify","then","resultCode","resultMessage","validateKMS","jwt","resolve","x5c","length","promise"],"sources":["kms-certificate-validation.js"],"sourcesContent":["import {parse as parseUrl} from 'url';\n\nimport {isUri} from 'valid-url';\nimport {fromBER} from 'asn1js';\nimport {\n Certificate,\n RSAPublicKey,\n CertificateChainValidationEngine,\n CryptoEngine,\n setEngine,\n} from 'pkijs';\nimport {isArray} from 'lodash';\nimport jose from 'node-jose';\nimport crypto from 'isomorphic-webcrypto';\nimport {Buffer} from 'safe-buffer';\n\nsetEngine(\n 'newEngine',\n crypto,\n new CryptoEngine({\n name: '',\n crypto,\n subtle: crypto.subtle,\n })\n);\n\nconst VALID_KTY = 'RSA';\nconst VALID_KID_PROTOCOL = 'kms:';\n\nconst X509_COMMON_NAME_KEY = '2.5.4.3';\n\nexport const X509_SUBJECT_ALT_NAME_KEY = '2.5.29.17';\n\n/**\n * Customize Error so the SDK knows to quit retrying and notify\n * the user\n */\nexport class KMSError extends Error {\n /**\n * add kmsError field to notify\n * @param {string} message\n */\n constructor(message) {\n super(message);\n this.kmsError = true;\n }\n}\n\nconst throwError = (err) => {\n throw new KMSError(`INVALID KMS: ${err}`);\n};\n\n/**\n * Converts the PEM string to a pkijs certificate object\n * @param {string} pem PEM representation of a certificate\n * @returns {Certificate} pkijs object of the certificate\n */\nconst decodeCert = (pem) => {\n if (typeof pem !== 'string') {\n throwError('certificate needs to be a string');\n }\n\n const der = Buffer.from(pem, 'base64');\n const ber = new Uint8Array(der).buffer;\n\n const asn1 = fromBER(ber);\n\n return new Certificate({schema: asn1.result});\n};\n\n/**\n * Validate the 'kty' property of the KMS credentials\n * @param {Object} JWT KMS credentials\n * @param {string} JWT.kty type of certificate\n * @throws {KMSError} if kty is not a valid type\n * @returns {void}\n */\nconst validateKtyHeader = ({kty}) => {\n if (kty !== VALID_KTY) {\n throwError(`'kty' header must be '${VALID_KTY}'`);\n }\n};\n\nconst validateKidHeader = ({kid}) => {\n if (!isUri(kid)) {\n throwError(\"'kid' is not a valid URI\");\n }\n\n if (parseUrl(kid).protocol !== VALID_KID_PROTOCOL) {\n throwError(`'kid' protocol must be '${VALID_KID_PROTOCOL}'`);\n }\n};\n\n/**\n * Checks the first certificate matches the 'kid' in the JWT.\n * It first checks the Subject Alternative Name then it checks\n * the Common Name\n * @param {Certificate} certificate represents the KMS\n * @param {Object} JWT KMS credentials\n * @param {string} JWT.kid the uri of the KMS\n * @throws {KMSError} if unable to validate certificate against KMS credentials\n * @returns {void}\n */\nexport const validateCommonName = ([certificate], {kid}) => {\n const kidHostname = parseUrl(kid).hostname;\n let validationSuccessful = false;\n\n if (certificate.extensions) {\n // Subject Alt Names are in here\n for (const extension of certificate.extensions) {\n if (extension.extnID === X509_SUBJECT_ALT_NAME_KEY) {\n const {altNames} = extension.parsedValue;\n\n for (const entry of altNames) {\n const san = entry.value.toLowerCase();\n\n validationSuccessful = san === kidHostname;\n if (validationSuccessful) {\n break;\n }\n }\n\n if (validationSuccessful) {\n break;\n }\n }\n }\n }\n\n if (!validationSuccessful) {\n // Didn't match kid in the Subject Alt Names, checking the Common Name\n const subjectAttributes = certificate.subject.typesAndValues;\n\n for (const attribute of subjectAttributes) {\n if (attribute.type === X509_COMMON_NAME_KEY) {\n const commonName = attribute.value.valueBlock.value;\n\n validationSuccessful = commonName === kidHostname;\n if (validationSuccessful) {\n break;\n }\n }\n }\n }\n\n if (!validationSuccessful) {\n throwError(\"hostname of the 1st certificate does not match 'kid'\");\n }\n};\n\n/**\n * Validate the first KMS certificate against the information\n * provided in the JWT\n * @param {Certificate} certificate first certificate the identifies the KMS\n * @param {Object} JWT credentials of the KMS\n * @param {string} JWT.e Public exponent of the first certificate\n * @param {string} KWT.n Modulus of the first certificate\n * @throws {KMSError} if e or n doesn't match the first certificate\n * @returns {void}\n */\nconst validatePublicCertificate = ([certificate], {e: publicExponent, n: modulus}) => {\n const {encode} = jose.util.base64url;\n\n const publicKey = certificate.subjectPublicKeyInfo.subjectPublicKey;\n const asn1PublicCert = fromBER(publicKey.valueBlock.valueHex);\n const publicCert = new RSAPublicKey({schema: asn1PublicCert.result});\n const publicExponentHex = publicCert.publicExponent.valueBlock.valueHex;\n const modulusHex = publicCert.modulus.valueBlock.valueHex;\n\n if (publicExponent !== encode(publicExponentHex)) {\n throwError('Public exponent is invalid');\n }\n if (modulus !== encode(modulusHex)) {\n throwError('Modulus is invalid');\n }\n};\n\n/**\n * Validates the list of certificates against the CAs provided\n * @param {certificate[]} certificates list of certificates provided\n * by the KMS to certify itself\n * @param {string[]} [caroots=[]] list of Certificate Authorities used to\n * validate the KMS's certificates\n * @returns {Promise} rejects if unable to validate the certificates\n */\nconst validateCertificatesSignature = (certificates, caroots = []) => {\n const certificateEngine = new CertificateChainValidationEngine({\n trustedCerts: caroots.map(decodeCert),\n certs: certificates,\n });\n\n return certificateEngine.verify().then(({result, resultCode, resultMessage}) => {\n if (!result) {\n throwError(`Certificate Validation failed [${resultCode}]: ${resultMessage}`);\n }\n });\n};\n\n/**\n * Validates the information provided by the KMS. This is a curried function.\n * The first function takes the caroots param and returns a second function.\n * The second function takes the credentials of the KMS and validates it\n * @param {string[]} caroots PEM encoded certificates that will be used\n * as Certificate Authorities\n * @param {Object} jwt Object containing the fields necessary to\n * validate the KMS\n * @returns {Promise} when resolved will return the jwt\n */\nconst validateKMS =\n (caroots) =>\n (jwt = {}) =>\n Promise.resolve().then(() => {\n validateKtyHeader(jwt);\n validateKidHeader(jwt);\n\n if (!(isArray(jwt.x5c) && jwt.x5c.length > 0)) {\n throwError('JWK does not contain a list of certificates');\n }\n const certificates = jwt.x5c.map(decodeCert);\n\n validateCommonName(certificates, jwt);\n validatePublicCertificate(certificates, jwt);\n\n // Skip validating signatures if no CA roots were provided\n const promise = caroots\n ? validateCertificatesSignature(certificates, caroots)\n : Promise.resolve();\n\n return promise.then(() => jwt);\n });\n\nexport default validateKMS;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAEA;AACA;AACA;AAQA;AACA;AACA;AAAmC;AAAA;AAAA;AAAA;AAAA;AAEnC,IAAAA,gBAAS,EACP,WAAW,EACXC,4BAAM,EACN,IAAIC,mBAAY,CAAC;EACfC,IAAI,EAAE,EAAE;EACRF,MAAM,EAANA,4BAAM;EACNG,MAAM,EAAEH,4BAAM,CAACG;AACjB,CAAC,CAAC,CACH;AAED,IAAMC,SAAS,GAAG,KAAK;AACvB,IAAMC,kBAAkB,GAAG,MAAM;AAEjC,IAAMC,oBAAoB,GAAG,SAAS;AAE/B,IAAMC,yBAAyB,GAAG,WAAW;;AAEpD;AACA;AACA;AACA;AAHA;AAAA,IAIaC,QAAQ;EAAA;EAAA;EACnB;AACF;AACA;AACA;EACE,kBAAYC,OAAO,EAAE;IAAA;IAAA;IACnB,0BAAMA,OAAO;IACb,MAAKC,QAAQ,GAAG,IAAI;IAAC;EACvB;EAAC;AAAA,+CAR2BC,KAAK;AAAA;AAWnC,IAAMC,UAAU,GAAG,SAAbA,UAAU,CAAIC,GAAG,EAAK;EAC1B,MAAM,IAAIL,QAAQ,wBAAiBK,GAAG,EAAG;AAC3C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,IAAMC,UAAU,GAAG,SAAbA,UAAU,CAAIC,GAAG,EAAK;EAC1B,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE;IAC3BH,UAAU,CAAC,kCAAkC,CAAC;EAChD;EAEA,IAAMI,GAAG,GAAGC,kBAAM,CAACC,IAAI,CAACH,GAAG,EAAE,QAAQ,CAAC;EACtC,IAAMI,GAAG,GAAG,IAAIC,UAAU,CAACJ,GAAG,CAAC,CAACK,MAAM;EAEtC,IAAMC,IAAI,GAAG,IAAAC,eAAO,EAACJ,GAAG,CAAC;EAEzB,OAAO,IAAIK,kBAAW,CAAC;IAACC,MAAM,EAAEH,IAAI,CAACI;EAAM,CAAC,CAAC;AAC/C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAMC,iBAAiB,GAAG,SAApBA,iBAAiB,OAAc;EAAA,IAATC,GAAG,QAAHA,GAAG;EAC7B,IAAIA,GAAG,KAAKxB,SAAS,EAAE;IACrBQ,UAAU,iCAA0BR,SAAS,OAAI;EACnD;AACF,CAAC;AAED,IAAMyB,iBAAiB,GAAG,SAApBA,iBAAiB,QAAc;EAAA,IAATC,GAAG,SAAHA,GAAG;EAC7B,IAAI,CAAC,IAAAC,eAAK,EAACD,GAAG,CAAC,EAAE;IACflB,UAAU,CAAC,0BAA0B,CAAC;EACxC;EAEA,IAAI,IAAAoB,UAAQ,EAACF,GAAG,CAAC,CAACG,QAAQ,KAAK5B,kBAAkB,EAAE;IACjDO,UAAU,mCAA4BP,kBAAkB,OAAI;EAC9D;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,IAAM6B,kBAAkB,GAAG,SAArBA,kBAAkB,eAA6B;EAAA;IAAxBC,WAAW;EAAA,IAAIL,GAAG,SAAHA,GAAG;EACpD,IAAMM,WAAW,GAAG,IAAAJ,UAAQ,EAACF,GAAG,CAAC,CAACO,QAAQ;EAC1C,IAAIC,oBAAoB,GAAG,KAAK;EAEhC,IAAIH,WAAW,CAACI,UAAU,EAAE;IAC1B;IAAA,2CACwBJ,WAAW,CAACI,UAAU;MAAA;IAAA;MAA9C,oDAAgD;QAAA,IAArCC,SAAS;QAClB,IAAIA,SAAS,CAACC,MAAM,KAAKlC,yBAAyB,EAAE;UAClD,IAAOmC,QAAQ,GAAIF,SAAS,CAACG,WAAW,CAAjCD,QAAQ;UAA0B,4CAErBA,QAAQ;YAAA;UAAA;YAA5B,uDAA8B;cAAA,IAAnBE,KAAK;cACd,IAAMC,GAAG,GAAGD,KAAK,CAACE,KAAK,CAACC,WAAW,EAAE;cAErCT,oBAAoB,GAAGO,GAAG,KAAKT,WAAW;cAC1C,IAAIE,oBAAoB,EAAE;gBACxB;cACF;YACF;UAAC;YAAA;UAAA;YAAA;UAAA;UAED,IAAIA,oBAAoB,EAAE;YACxB;UACF;QACF;MACF;IAAC;MAAA;IAAA;MAAA;IAAA;EACH;EAEA,IAAI,CAACA,oBAAoB,EAAE;IACzB;IACA,IAAMU,iBAAiB,GAAGb,WAAW,CAACc,OAAO,CAACC,cAAc;IAAC,4CAErCF,iBAAiB;MAAA;IAAA;MAAzC,uDAA2C;QAAA,IAAhCG,SAAS;QAClB,IAAIA,SAAS,CAACC,IAAI,KAAK9C,oBAAoB,EAAE;UAC3C,IAAM+C,UAAU,GAAGF,SAAS,CAACL,KAAK,CAACQ,UAAU,CAACR,KAAK;UAEnDR,oBAAoB,GAAGe,UAAU,KAAKjB,WAAW;UACjD,IAAIE,oBAAoB,EAAE;YACxB;UACF;QACF;MACF;IAAC;MAAA;IAAA;MAAA;IAAA;EACH;EAEA,IAAI,CAACA,oBAAoB,EAAE;IACzB1B,UAAU,CAAC,sDAAsD,CAAC;EACpE;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AAUA,IAAM2C,yBAAyB,GAAG,SAA5BA,yBAAyB,eAAuD;EAAA;IAAlDpB,WAAW;EAAA,IAAOqB,cAAc,SAAjBC,CAAC;IAAqBC,OAAO,SAAVC,CAAC;EACrE,IAAOC,MAAM,GAAIC,iBAAI,CAACC,IAAI,CAACC,SAAS,CAA7BH,MAAM;EAEb,IAAMI,SAAS,GAAG7B,WAAW,CAAC8B,oBAAoB,CAACC,gBAAgB;EACnE,IAAMC,cAAc,GAAG,IAAA5C,eAAO,EAACyC,SAAS,CAACV,UAAU,CAACc,QAAQ,CAAC;EAC7D,IAAMC,UAAU,GAAG,IAAIC,mBAAY,CAAC;IAAC7C,MAAM,EAAE0C,cAAc,CAACzC;EAAM,CAAC,CAAC;EACpE,IAAM6C,iBAAiB,GAAGF,UAAU,CAACb,cAAc,CAACF,UAAU,CAACc,QAAQ;EACvE,IAAMI,UAAU,GAAGH,UAAU,CAACX,OAAO,CAACJ,UAAU,CAACc,QAAQ;EAEzD,IAAIZ,cAAc,KAAKI,MAAM,CAACW,iBAAiB,CAAC,EAAE;IAChD3D,UAAU,CAAC,4BAA4B,CAAC;EAC1C;EACA,IAAI8C,OAAO,KAAKE,MAAM,CAACY,UAAU,CAAC,EAAE;IAClC5D,UAAU,CAAC,oBAAoB,CAAC;EAClC;AACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAM6D,6BAA6B,GAAG,SAAhCA,6BAA6B,CAAIC,YAAY,EAAmB;EAAA,IAAjBC,OAAO,uEAAG,EAAE;EAC/D,IAAMC,iBAAiB,GAAG,IAAIC,uCAAgC,CAAC;IAC7DC,YAAY,EAAEH,OAAO,CAACI,GAAG,CAACjE,UAAU,CAAC;IACrCkE,KAAK,EAAEN;EACT,CAAC,CAAC;EAEF,OAAOE,iBAAiB,CAACK,MAAM,EAAE,CAACC,IAAI,CAAC,iBAAyC;IAAA,IAAvCxD,MAAM,SAANA,MAAM;MAAEyD,UAAU,SAAVA,UAAU;MAAEC,aAAa,SAAbA,aAAa;IACxE,IAAI,CAAC1D,MAAM,EAAE;MACXd,UAAU,0CAAmCuE,UAAU,gBAAMC,aAAa,EAAG;IAC/E;EACF,CAAC,CAAC;AACJ,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAMC,WAAW,GACf,SADIA,WAAW,CACdV,OAAO;EAAA,OACR;IAAA,IAACW,GAAG,uEAAG,CAAC,CAAC;IAAA,OACP,iBAAQC,OAAO,EAAE,CAACL,IAAI,CAAC,YAAM;MAC3BvD,iBAAiB,CAAC2D,GAAG,CAAC;MACtBzD,iBAAiB,CAACyD,GAAG,CAAC;MAEtB,IAAI,EAAE,uBAAQA,GAAG,CAACE,GAAG,CAAC,IAAIF,GAAG,CAACE,GAAG,CAACC,MAAM,GAAG,CAAC,CAAC,EAAE;QAC7C7E,UAAU,CAAC,6CAA6C,CAAC;MAC3D;MACA,IAAM8D,YAAY,GAAGY,GAAG,CAACE,GAAG,CAACT,GAAG,CAACjE,UAAU,CAAC;MAE5CoB,kBAAkB,CAACwC,YAAY,EAAEY,GAAG,CAAC;MACrC/B,yBAAyB,CAACmB,YAAY,EAAEY,GAAG,CAAC;;MAE5C;MACA,IAAMI,OAAO,GAAGf,OAAO,GACnBF,6BAA6B,CAACC,YAAY,EAAEC,OAAO,CAAC,GACpD,iBAAQY,OAAO,EAAE;MAErB,OAAOG,OAAO,CAACR,IAAI,CAAC;QAAA,OAAMI,GAAG;MAAA,EAAC;IAChC,CAAC,CAAC;EAAA;AAAA;AAAC,eAEQD,WAAW;AAAA"}
|
package/dist/kms-errors.js
CHANGED
|
@@ -66,6 +66,12 @@ var KmsError = /*#__PURE__*/function (_Exception) {
|
|
|
66
66
|
if (body.requestId) {
|
|
67
67
|
message += "\nKMS_REQUEST_ID: ".concat(body.requestId);
|
|
68
68
|
}
|
|
69
|
+
if (body.statusCode) {
|
|
70
|
+
message += "\nKMS_STATUS_CODE: ".concat(body.statusCode);
|
|
71
|
+
}
|
|
72
|
+
if (body.errorCode) {
|
|
73
|
+
message += "\nKMS_ErrorCode: ".concat(body.errorCode);
|
|
74
|
+
}
|
|
69
75
|
return message;
|
|
70
76
|
}
|
|
71
77
|
}]);
|
package/dist/kms-errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["KmsError","body","enumerable","value","reason","requestId","status","message","constructor","defaultMessage","Exception","KmsTimeoutError","request","timeout","method","uri","DryError","WebexHttpError","prototype","parse","_res","options","url","service","toUpperCase","resource","headers","trackingid"],"sources":["kms-errors.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {Exception} from '@webex/common';\nimport {WebexHttpError} from '@webex/webex-core';\n\n/**\n * Error class for KMS errors\n */\nexport class KmsError extends Exception {\n static defaultMessage =\n 'An unknown error occurred while communicating with the kms. This implies we received an error response without a body.';\n\n /**\n * @param {HttpResponse} body\n * @returns {string}\n */\n parse(body) {\n body = body.body || body;\n\n Object.defineProperties(this, {\n body: {\n enumerable: false,\n value: body,\n },\n reason: {\n enumerable: false,\n value: body.reason,\n },\n requestId: {\n enumerable: false,\n value: body.requestId,\n },\n status: {\n enumerable: false,\n value: body.status,\n },\n });\n\n let message = typeof body === 'string' ? body : body.reason;\n\n if (!message) {\n message = this.constructor.defaultMessage;\n }\n if (body.status) {\n message += `\\nKMS_RESPONSE_STATUS: ${body.status}`;\n }\n if (body.requestId) {\n message += `\\nKMS_REQUEST_ID: ${body.requestId}`;\n }\n\n return message;\n }\n}\n\n/**\n * Thrown when an expected KMSResponse is not received in a timely manner\n */\nexport class KmsTimeoutError extends KmsError {\n /**\n * @param {KmsRequest} options.request\n * @param {KmsRequest} options.timeout\n * @returns {string}\n */\n parse({request = {}, timeout} = {}) {\n let message = `The KMS did not respond within ${\n timeout ? `${timeout} milliseconds` : 'a timely fashion'\n }`;\n\n if (request) {\n if (request.method && request.uri) {\n message += `\\nKMS_REQUEST: ${request.method} ${request.uri}`;\n }\n\n if (request.requestId) {\n message += `\\nKMS_REQUEST_ID: ${request.requestId}`;\n }\n }\n\n return message;\n }\n}\n\n/**\n * Emitted when a REST request includes an encrypter error\n */\nexport class DryError extends WebexHttpError {\n static defaultMessage = 'An unknown error was received from a service that proxies to the KMS';\n\n /**\n * @param {WebexHttpError} reason\n * @returns {string}\n */\n parse(reason) {\n Reflect.apply(WebexHttpError.prototype.parse, this, [reason._res]);\n const body = reason._res.body.message;\n\n let message = body.reason || body;\n\n if (!message) {\n message = this.constructor.defaultMessage;\n }\n if (this.options.url) {\n message += `\\n${this.options.method} ${this.options.url}`;\n } else if (this.options.uri) {\n message += `\\n${this.options.method} ${this.options.uri}`;\n } else {\n message += `\\n${this.options.method} ${this.options.service.toUpperCase()}/${\n this.options.resource\n }`;\n }\n message += `\\nWEBEX_TRACKING_ID: ${this.options.headers.trackingid}`;\n\n if (body.status) {\n message += `\\nKMS_RESPONSE_STATUS: ${body.status}`;\n }\n if (body.requestId) {\n message += `\\nKMS_REQUEST_ID: ${body.requestId}`;\n }\n\n Object.defineProperties(this, {\n reason: {\n enumerable: false,\n value: body.reason,\n },\n requestId: {\n enumerable: false,\n value: body.requestId,\n },\n status: {\n enumerable: false,\n value: body.status,\n },\n });\n\n return message;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAIA;AACA;AAAiD;AAAA;AAEjD;AACA;AACA;AAFA,IAGaA,QAAQ;EAAA;EAAA;EAAA;IAAA;IAAA;EAAA;EAAA;IAAA;IAAA;IAInB;AACF;AACA;AACA;IACE,eAAMC,IAAI,EAAE;MACVA,IAAI,GAAGA,IAAI,CAACA,IAAI,IAAIA,IAAI;MAExB,+BAAwB,IAAI,EAAE;QAC5BA,IAAI,EAAE;UACJC,UAAU,EAAE,KAAK;UACjBC,KAAK,EAAEF;QACT,CAAC;QACDG,MAAM,EAAE;UACNF,UAAU,EAAE,KAAK;UACjBC,KAAK,EAAEF,IAAI,CAACG;QACd,CAAC;QACDC,SAAS,EAAE;UACTH,UAAU,EAAE,KAAK;UACjBC,KAAK,EAAEF,IAAI,CAACI;QACd,CAAC;QACDC,MAAM,EAAE;UACNJ,UAAU,EAAE,KAAK;UACjBC,KAAK,EAAEF,IAAI,CAACK;QACd;MACF,CAAC,CAAC;MAEF,IAAIC,OAAO,GAAG,OAAON,IAAI,KAAK,QAAQ,GAAGA,IAAI,GAAGA,IAAI,CAACG,MAAM;MAE3D,IAAI,CAACG,OAAO,EAAE;QACZA,OAAO,GAAG,IAAI,CAACC,WAAW,CAACC,cAAc;MAC3C;MACA,IAAIR,IAAI,CAACK,MAAM,EAAE;QACfC,OAAO,qCAA8BN,IAAI,CAACK,MAAM,CAAE;MACpD;MACA,IAAIL,IAAI,CAACI,SAAS,EAAE;QAClBE,OAAO,gCAAyBN,IAAI,CAACI,SAAS,CAAE;MAClD;MAEA,
|
|
1
|
+
{"version":3,"names":["KmsError","body","enumerable","value","reason","requestId","status","message","constructor","defaultMessage","statusCode","errorCode","Exception","KmsTimeoutError","request","timeout","method","uri","DryError","WebexHttpError","prototype","parse","_res","options","url","service","toUpperCase","resource","headers","trackingid"],"sources":["kms-errors.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport {Exception} from '@webex/common';\nimport {WebexHttpError} from '@webex/webex-core';\n\n/**\n * Error class for KMS errors\n */\nexport class KmsError extends Exception {\n static defaultMessage =\n 'An unknown error occurred while communicating with the kms. This implies we received an error response without a body.';\n\n /**\n * @param {HttpResponse} body\n * @returns {string}\n */\n parse(body) {\n body = body.body || body;\n\n Object.defineProperties(this, {\n body: {\n enumerable: false,\n value: body,\n },\n reason: {\n enumerable: false,\n value: body.reason,\n },\n requestId: {\n enumerable: false,\n value: body.requestId,\n },\n status: {\n enumerable: false,\n value: body.status,\n },\n });\n\n let message = typeof body === 'string' ? body : body.reason;\n\n if (!message) {\n message = this.constructor.defaultMessage;\n }\n if (body.status) {\n message += `\\nKMS_RESPONSE_STATUS: ${body.status}`;\n }\n if (body.requestId) {\n message += `\\nKMS_REQUEST_ID: ${body.requestId}`;\n }\n\n if (body.statusCode) {\n message += `\\nKMS_STATUS_CODE: ${body.statusCode}`;\n }\n\n if (body.errorCode) {\n message += `\\nKMS_ErrorCode: ${body.errorCode}`;\n }\n\n return message;\n }\n}\n\n/**\n * Thrown when an expected KMSResponse is not received in a timely manner\n */\nexport class KmsTimeoutError extends KmsError {\n /**\n * @param {KmsRequest} options.request\n * @param {KmsRequest} options.timeout\n * @returns {string}\n */\n parse({request = {}, timeout} = {}) {\n let message = `The KMS did not respond within ${\n timeout ? `${timeout} milliseconds` : 'a timely fashion'\n }`;\n\n if (request) {\n if (request.method && request.uri) {\n message += `\\nKMS_REQUEST: ${request.method} ${request.uri}`;\n }\n\n if (request.requestId) {\n message += `\\nKMS_REQUEST_ID: ${request.requestId}`;\n }\n }\n\n return message;\n }\n}\n\n/**\n * Emitted when a REST request includes an encrypter error\n */\nexport class DryError extends WebexHttpError {\n static defaultMessage = 'An unknown error was received from a service that proxies to the KMS';\n\n /**\n * @param {WebexHttpError} reason\n * @returns {string}\n */\n parse(reason) {\n Reflect.apply(WebexHttpError.prototype.parse, this, [reason._res]);\n const body = reason._res.body.message;\n\n let message = body.reason || body;\n\n if (!message) {\n message = this.constructor.defaultMessage;\n }\n if (this.options.url) {\n message += `\\n${this.options.method} ${this.options.url}`;\n } else if (this.options.uri) {\n message += `\\n${this.options.method} ${this.options.uri}`;\n } else {\n message += `\\n${this.options.method} ${this.options.service.toUpperCase()}/${\n this.options.resource\n }`;\n }\n message += `\\nWEBEX_TRACKING_ID: ${this.options.headers.trackingid}`;\n\n if (body.status) {\n message += `\\nKMS_RESPONSE_STATUS: ${body.status}`;\n }\n if (body.requestId) {\n message += `\\nKMS_REQUEST_ID: ${body.requestId}`;\n }\n\n Object.defineProperties(this, {\n reason: {\n enumerable: false,\n value: body.reason,\n },\n requestId: {\n enumerable: false,\n value: body.requestId,\n },\n status: {\n enumerable: false,\n value: body.status,\n },\n });\n\n return message;\n }\n}\n"],"mappings":"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"}
|
package/dist/kms.js
CHANGED
|
@@ -294,16 +294,19 @@ var KMS = _webexCore.WebexPlugin.extend((_dec = (0, _common.oneFlight)({
|
|
|
294
294
|
* @param {Object} options
|
|
295
295
|
* @param {UUID} options.assignedOrgId the orgId
|
|
296
296
|
* @param {string} options.customerMasterKey the master key
|
|
297
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
297
298
|
* @returns {Promise.<UploadCmkResponse>} response of upload CMK api
|
|
298
299
|
*/
|
|
299
300
|
uploadCustomerMasterKey: function uploadCustomerMasterKey(_ref9) {
|
|
300
301
|
var _this8 = this;
|
|
301
302
|
var assignedOrgId = _ref9.assignedOrgId,
|
|
302
|
-
customerMasterKey = _ref9.customerMasterKey
|
|
303
|
+
customerMasterKey = _ref9.customerMasterKey,
|
|
304
|
+
_ref9$awsKms = _ref9.awsKms,
|
|
305
|
+
awsKms = _ref9$awsKms === void 0 ? false : _ref9$awsKms;
|
|
303
306
|
this.logger.info('kms: upload customer master key for byok');
|
|
304
307
|
return this.request({
|
|
305
308
|
method: 'create',
|
|
306
|
-
uri: '/cmk',
|
|
309
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
307
310
|
assignedOrgId: assignedOrgId,
|
|
308
311
|
customerMasterKey: customerMasterKey,
|
|
309
312
|
requestId: _uuid.default.v4()
|
|
@@ -316,15 +319,18 @@ var KMS = _webexCore.WebexPlugin.extend((_dec = (0, _common.oneFlight)({
|
|
|
316
319
|
* get all customer master keys for one org.
|
|
317
320
|
* @param {Object} options
|
|
318
321
|
* @param {UUID} options.assignedOrgId the orgId
|
|
322
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
319
323
|
* @returns {Promise.<ActivateCmkResponse>} response of list CMKs api
|
|
320
324
|
*/
|
|
321
325
|
listAllCustomerMasterKey: function listAllCustomerMasterKey(_ref10) {
|
|
322
326
|
var _this9 = this;
|
|
323
|
-
var assignedOrgId = _ref10.assignedOrgId
|
|
327
|
+
var assignedOrgId = _ref10.assignedOrgId,
|
|
328
|
+
_ref10$awsKms = _ref10.awsKms,
|
|
329
|
+
awsKms = _ref10$awsKms === void 0 ? false : _ref10$awsKms;
|
|
324
330
|
this.logger.info('kms: get all customer master keys for byok');
|
|
325
331
|
return this.request({
|
|
326
332
|
method: 'retrieve',
|
|
327
|
-
uri: '/cmk',
|
|
333
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
328
334
|
assignedOrgId: assignedOrgId,
|
|
329
335
|
requestId: _uuid.default.v4()
|
|
330
336
|
}).then(function (res) {
|
|
@@ -380,15 +386,18 @@ var KMS = _webexCore.WebexPlugin.extend((_dec = (0, _common.oneFlight)({
|
|
|
380
386
|
* this is for test case. it will delete all CMKs, no matter what their status is. This is mainly for test purpose
|
|
381
387
|
* @param {Object} options
|
|
382
388
|
* @param {UUID} options.assignedOrgId the orgId
|
|
389
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
383
390
|
* @returns {Promise.<{status, requestId}>}
|
|
384
391
|
*/
|
|
385
392
|
deleteAllCustomerMasterKeys: function deleteAllCustomerMasterKeys(_ref12) {
|
|
386
393
|
var _this11 = this;
|
|
387
|
-
var assignedOrgId = _ref12.assignedOrgId
|
|
394
|
+
var assignedOrgId = _ref12.assignedOrgId,
|
|
395
|
+
_ref12$awsKms = _ref12.awsKms,
|
|
396
|
+
awsKms = _ref12$awsKms === void 0 ? false : _ref12$awsKms;
|
|
388
397
|
this.logger.info('kms: delete all customer master keys at the same time');
|
|
389
398
|
return this.request({
|
|
390
399
|
method: 'delete',
|
|
391
|
-
uri: '/cmk',
|
|
400
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
392
401
|
assignedOrgId: assignedOrgId,
|
|
393
402
|
requestId: _uuid.default.v4()
|
|
394
403
|
}).then(function (res) {
|
|
@@ -793,7 +802,7 @@ var KMS = _webexCore.WebexPlugin.extend((_dec = (0, _common.oneFlight)({
|
|
|
793
802
|
context.ephemeralKey = originalContext.ephemeralKey;
|
|
794
803
|
return context;
|
|
795
804
|
},
|
|
796
|
-
version: "3.0.0-beta.
|
|
805
|
+
version: "3.0.0-beta.210"
|
|
797
806
|
}, ((0, _applyDecoratedDescriptor2.default)(_obj, "fetchKey", [_dec], (0, _getOwnPropertyDescriptor.default)(_obj, "fetchKey"), _obj), (0, _applyDecoratedDescriptor2.default)(_obj, "_getContext", [_common.oneFlight], (0, _getOwnPropertyDescriptor.default)(_obj, "_getContext"), _obj)), _obj)));
|
|
798
807
|
var _default = KMS;
|
|
799
808
|
exports.default = _default;
|
package/dist/kms.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["contexts","kmsDetails","partialContexts","consoleDebug","require","KMS","WebexPlugin","extend","oneFlight","keyFactory","uri","onBehalfOf","namespace","children","batcher","KMSBatcher","bindKey","kro","kroUri","key","keyUri","logger","info","reject","Error","request","method","resourceUri","then","res","createResource","userIds","keyUris","keys","reduce","uris","k","push","length","resource","addAuthorization","authIds","concat","authorizations","listAuthorizations","removeAuthorization","authId","userId","querystring","stringify","createUnboundKeys","count","all","map","asKey","fetchPublicKey","assignedOrgId","publicKey","uploadCustomerMasterKey","customerMasterKey","requestId","uuid","v4","listAllCustomerMasterKey","changeCustomerMasterKeyState","keyId","keyState","deleteAllCustomerMasterKeys","useGlobalMasterKey","fetchKey","ping","jose","JWK","jwk","prepareRequest","payload","isECDHRequest","includes","resolve","get","_getContext","context","req","Request","requestContext","_contextOnBehalfOf","wrap","serverKey","process","env","NODE_ENV","util","inspect","JSON","parse","depth","processKmsMessageEvent","event","encryption","kmsMessages","kmsMessage","index","_isECDHEMessage","isECDHMessage","Response","unwrap","catch","reason","error","stack","decryptKmsMessage","body","_getKMSStaticPubKey","kmsStaticPubKey","fields","split","header","base64url","decode","kid","timeout","config","kmsInitialTimeout","webex","internal","mercury","connect","TIMEOUT_SYMBOL","status","statusCode","message","match","warn","KMSError","trigger","ecdhMaxTimeout","nextTimeout","kmsMaxTimeout","delete","_getAuthorization","credentials","getUserToken","token","access_token","promise","_prepareContext","set","expiresIn","ephemeralKey","expirationDate","safeSetTimeout","authorization","clientInfo","credential","bearer","_getKMSCluster","_getKMSDetails","kmsCluster","details","service","device","rsaPublicKey","Context","validateKMS","caroots","clientId","url","serverInfo","createECDHKey","localECDHKey","cluster","toJSON","deriveEphemeralKey","originalContext"],"sources":["kms.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport querystring from 'querystring';\nimport util from 'util';\n\nimport {safeSetTimeout} from '@webex/common-timers';\nimport {oneFlight} from '@webex/common';\nimport {WebexPlugin} from '@webex/webex-core';\nimport {Context, Request, Response} from 'node-kms';\nimport jose from 'node-jose';\nimport {omit} from 'lodash';\nimport uuid from 'uuid';\n\nimport KMSBatcher, {TIMEOUT_SYMBOL} from './kms-batcher';\nimport validateKMS, {KMSError} from './kms-certificate-validation';\n\nconst contexts = new WeakMap();\nconst kmsDetails = new WeakMap();\nconst partialContexts = new WeakMap();\n\nconst consoleDebug = require('debug')('kms');\n\n/**\n * @class\n */\nconst KMS = WebexPlugin.extend({\n namespace: 'Encryption',\n\n children: {\n batcher: KMSBatcher,\n },\n\n /**\n * Binds a key to a resource\n * @param {Object} options\n * @param {KMSResourceObject} options.kro\n * @param {string} options.kroUri\n * @param {Key} options.key\n * @param {string} options.keyUri\n * @returns {Promise<Key>}\n */\n bindKey({kro, kroUri, key, keyUri}) {\n kroUri = kroUri || kro.uri;\n keyUri = keyUri || key.uri;\n\n this.logger.info('kms: binding key to resource');\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n /* istanbul ignore if */\n if (!keyUri) {\n return Promise.reject(new Error('`key` or `keyUri` is required'));\n }\n\n return this.request({\n method: 'update',\n resourceUri: kroUri,\n uri: keyUri,\n }).then((res) => {\n this.logger.info('kms: bound key to resource');\n\n return res.key;\n });\n },\n\n /**\n * Creates a new KMS Resource\n * @param {Object} options\n * @param {Array<string>} options.userIds\n * @param {Array<string>} options.keyUris\n * @param {Key} options.key\n * @param {Array<Keys>} options.keys\n * @returns {Promise<KMSResourceObject>}\n */\n createResource({userIds, keyUris, key, keys}) {\n keyUris = keyUris || [];\n /* istanbul ignore if */\n if (keys) {\n keyUris = keys.reduce((uris, k) => {\n uris.push(k.uri);\n\n return uris;\n }, keyUris);\n }\n\n /* istanbul ignore else */\n if (key) {\n keyUris.push(key.uri);\n }\n\n /* istanbul ignore if */\n if (keyUris.length === 0) {\n return Promise.reject(new Error('Cannot create KMS Resource without at least one keyUri'));\n }\n\n this.logger.info('kms: creating resource');\n\n return this.request({\n method: 'create',\n uri: '/resources',\n userIds,\n keyUris,\n }).then((res) => {\n this.logger.info('kms: created resource');\n\n return res.resource;\n });\n },\n\n /**\n * Authorizes a user or KRO to a KRO\n * @param {Object} options\n * @param {Array<string>} options.userIds\n * @param {Array<string>} options.authIds interchangable with userIds\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Promise<KMSAuthorizationObject>}\n */\n addAuthorization({userIds, authIds, kro, kroUri}) {\n userIds = userIds || [];\n kroUri = kroUri || kro.uri;\n\n if (authIds) {\n userIds = userIds.concat(authIds);\n }\n\n /* istanbul ignore if */\n if (userIds.length === 0) {\n return Promise.reject(new Error('Cannot add authorization without userIds or authIds'));\n }\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n this.logger.info('kms: adding authorization to kms resource');\n\n return this.request({\n method: 'create',\n uri: '/authorizations',\n resourceUri: kroUri,\n userIds,\n }).then((res) => {\n this.logger.info('kms: added authorization');\n\n return res.authorizations;\n });\n },\n\n /**\n * Retrieve a list of users that have been authorized to the KRO\n * @param {Object} options\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Array<authId>}\n */\n listAuthorizations({kro, kroUri}) {\n kroUri = kroUri || kro.uri;\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n return this.request({\n method: 'retrieve',\n uri: `${kroUri}/authorizations`,\n }).then((res) => {\n this.logger.info('kms: retrieved authorization list');\n\n return res.authorizations;\n });\n },\n\n /**\n * Deauthorizes a user or KRO from a KRO\n * @param {Object} options\n * @param {string} options.userId\n * @param {string} options.authId interchangable with userIds\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Promise<KMSAuthorizationObject>}\n */\n removeAuthorization({authId, userId, kro, kroUri}) {\n authId = authId || userId;\n kroUri = kroUri || kro.uri;\n\n /* istanbul ignore if */\n if (!authId) {\n return Promise.reject(new Error('Cannot remove authorization without authId'));\n }\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n this.logger.info('kms: removing authorization from kms resource');\n\n return this.request({\n method: 'delete',\n uri: `${kroUri}/authorizations?${querystring.stringify({authId})}`,\n }).then((res) => {\n this.logger.info('kms: removed authorization');\n\n return res.authorizations;\n });\n },\n\n /**\n * Requests `count` unbound keys from the kms\n * @param {Object} options\n * @param {Number} options.count\n * @returns {Array<Key>}\n */\n createUnboundKeys({count}) {\n this.logger.info(`kms: request ${count} unbound keys`);\n\n /* istanbul ignore if */\n if (!count) {\n return Promise.reject(new Error('`options.count` is required'));\n }\n\n return this.request({\n method: 'create',\n uri: '/keys',\n count,\n }).then((res) => {\n this.logger.info('kms: received unbound keys');\n\n return Promise.all(res.keys.map(this.asKey));\n });\n },\n\n /**\n * @typedef {Object} FetchPublicKeyResponse\n * @property {number} status 200,400(Bad Request: Request payload missing info),404(Not Found: HSM Public Key not found),501(Not Implemented: This KMS does not support BYOK),502(Bad Gateway: KMS could not communicate with HSM)\n * @property {UUID} requestId this is should be unique, used for debug.\n * @property {string} publicKey\n */\n /**\n * get public key from kms\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<FetchPublicKeyResponse>} response of get public key api\n */\n fetchPublicKey({assignedOrgId}) {\n this.logger.info('kms: fetch public key for byok');\n\n return this.request({\n method: 'retrieve',\n uri: '/publicKey',\n assignedOrgId,\n }).then((res) => {\n this.logger.info('kms: received public key');\n\n return res.publicKey;\n });\n },\n\n /**\n * @typedef {Object} UploadCmkResponse\n * @property {number} status\n * @property {UUID} requestId\n * @property {string} uri\n * @property {string} keysState\n */\n /**\n * upload master key for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @param {string} options.customerMasterKey the master key\n * @returns {Promise.<UploadCmkResponse>} response of upload CMK api\n */\n uploadCustomerMasterKey({assignedOrgId, customerMasterKey}) {\n this.logger.info('kms: upload customer master key for byok');\n\n return this.request({\n method: 'create',\n uri: '/cmk',\n assignedOrgId,\n customerMasterKey,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to upload customer master key');\n\n return res;\n });\n },\n\n /**\n * get all customer master keys for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<ActivateCmkResponse>} response of list CMKs api\n */\n listAllCustomerMasterKey({assignedOrgId}) {\n this.logger.info('kms: get all customer master keys for byok');\n\n return this.request({\n method: 'retrieve',\n uri: '/cmk',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to get all customer master keys');\n\n return res;\n });\n },\n\n /**\n * @typedef {Object} ActivateCmkResponse\n * @property {number} status\n * @property {UUID} requestId\n * @property {Array<CMK>} customerMasterKeys\n */\n /**\n *\n * @typedef {Object} CMK\n * @property {string} usageState\n * @property {UUID} assignedOrgId\n * @property {string} uri\n * @property {string} source\n * @property {Date | undefined} stateUpdatedOn\n * @property {Date | undefined} rotation\n */\n /**\n * change one customer master key state for one org.\n * delete pending key, then the keyState should be 'removedclean';\n * active pending key, then the keyState should be 'active';\n *\n * @param {Object} options\n * @param {string} options.keyId the id of one customer master key, it should be a url\n * @param {string} options.keyState one of the following: PENDING, RECOVERING,ACTIVE,REVOKED,DEACTIVATED,REENCRYPTING,RETIRED,DELETED,DISABLED,REMOVEDCLEAN,REMOVEDDIRTY;\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<ActivateCmkResponse>} response of list CMKs api\n */\n changeCustomerMasterKeyState({keyId, keyState, assignedOrgId}) {\n this.logger.info('kms: change one customer master key state for byok');\n\n return this.request({\n method: 'update',\n uri: keyId,\n keyState,\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to change the customer master key state to {}', keyState);\n\n return res;\n });\n },\n\n /**\n * this is for test case. it will delete all CMKs, no matter what their status is. This is mainly for test purpose\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<{status, requestId}>}\n */\n deleteAllCustomerMasterKeys({assignedOrgId}) {\n this.logger.info('kms: delete all customer master keys at the same time');\n\n return this.request({\n method: 'delete',\n uri: '/cmk',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to delete all customer master keys');\n\n return res;\n });\n },\n\n /**\n * return to use global master key for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<ActivateCmkResponse>} response of activate CMK api\n */\n useGlobalMasterKey({assignedOrgId}) {\n this.logger.info('kms: return to use global master key');\n\n return this.request({\n method: 'update',\n uri: 'default',\n keyState: 'ACTIVE',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to return to global master key');\n\n return res;\n });\n },\n\n /**\n * Fetches the specified key from the kms\n * @param {Object} options\n * @param {string} options.uri\n * @param {string} options.onBehalfOf The id of a user, upon whose behalf, the key is to be retrieved or undefined if retrieval is for the active user\n * @returns {Promise<Key>}\n */\n // Ideally, this would be done via the kms batcher, but other than request id,\n // there isn't any other userful key in a kms response to match it to a\n // request. as such, we need the batcher to group requests, but one flight to\n // make sure we don't make the same request multiple times.\n @oneFlight({\n keyFactory: ({uri, onBehalfOf}) => `${uri}/${onBehalfOf}`,\n })\n fetchKey({uri, onBehalfOf}) {\n /* istanbul ignore if */\n if (!uri) {\n return Promise.reject(new Error('`options.uri` is required'));\n }\n\n this.logger.info('kms: fetching key');\n\n return this.request(\n {\n method: 'retrieve',\n uri,\n },\n {onBehalfOf}\n ).then((res) => {\n this.logger.info('kms: fetched key');\n\n return this.asKey(res.key);\n });\n },\n\n /**\n * Pings the kms. Mostly for testing\n * @returns {Promise}\n */\n ping() {\n return this.request({\n method: 'update',\n uri: '/ping',\n });\n },\n\n /**\n * Ensures a key obect is Key instance\n * @param {Object} key\n * @returns {Promise<Key>}\n */\n asKey(key) {\n return jose.JWK.asKey(key.jwk).then((jwk) => {\n key.jwk = jwk;\n\n return key;\n });\n },\n\n /**\n * Adds appropriate metadata to the KMS request\n * @param {Object} payload\n * @param {Object} onBehalfOf Optional parameter to prepare the request on behalf of another user\n * @returns {Promise<KMS.Request>}\n */\n prepareRequest(payload, onBehalfOf) {\n const isECDHRequest = payload.method === 'create' && payload.uri.includes('/ecdhe');\n\n return Promise.resolve(isECDHRequest ? partialContexts.get(this) : this._getContext()).then(\n (context) => {\n this.logger.info(`kms: wrapping ${isECDHRequest ? 'ephemeral key' : 'kms'} request`);\n const req = new Request(payload);\n let requestContext = context;\n\n if (onBehalfOf) {\n requestContext = this._contextOnBehalfOf(context, onBehalfOf);\n }\n\n return req.wrap(requestContext, {serverKey: isECDHRequest}).then(() => {\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info(\n 'kms: request payload',\n util.inspect(omit(JSON.parse(JSON.stringify(req)), 'wrapped'), {depth: null})\n );\n }\n\n return req;\n });\n }\n );\n },\n\n /**\n * Accepts a kms message event, decrypts it, and passes it to the batcher\n * @param {Object} event\n * @returns {Promise<Object>}\n */\n processKmsMessageEvent(event) {\n this.logger.info('kms: received kms message');\n\n return Promise.all(\n event.encryption.kmsMessages.map((kmsMessage, index) =>\n this._isECDHEMessage(kmsMessage).then((isECDHMessage) => {\n this.logger.info(`kms: received ${isECDHMessage ? 'ecdhe' : 'normal'} message`);\n const res = new Response(kmsMessage);\n\n return (\n Promise.resolve(isECDHMessage ? partialContexts.get(this) : contexts.get(this))\n // eslint-disable-next-line max-nested-callbacks\n .then((context) => res.unwrap(context))\n // eslint-disable-next-line max-nested-callbacks\n .then(() => {\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info(\n 'kms: response payload',\n util.inspect(omit(JSON.parse(JSON.stringify(res)), 'wrapped'), {depth: null})\n );\n }\n })\n // eslint-disable-next-line max-nested-callbacks\n .then(() => {\n event.encryption.kmsMessages[index] = res;\n })\n // eslint-disable-next-line max-nested-callbacks\n .then(() => res)\n );\n })\n )\n )\n .then(() => this.batcher.processKmsMessageEvent(event))\n .catch((reason) => {\n this.logger.error('kms: decrypt failed', reason.stack);\n\n return Promise.reject(reason);\n })\n .then(() => event);\n },\n\n /**\n * Decrypts a kms message\n * @param {Object} kmsMessage\n * @returns {Promise<Object>}\n */\n decryptKmsMessage(kmsMessage) {\n const res = new Response(kmsMessage);\n\n return contexts\n .get(this)\n .then((context) => res.unwrap(context))\n .then(() => res.body);\n },\n\n /**\n * Determines if the kms message is an ecdhe message or a normal message\n * @param {Object} kmsMessage\n * @returns {Promise<boolean>}\n */\n _isECDHEMessage(kmsMessage) {\n return this._getKMSStaticPubKey().then((kmsStaticPubKey) => {\n const fields = kmsMessage.split('.');\n\n if (fields.length !== 3) {\n return false;\n }\n\n const header = JSON.parse(jose.util.base64url.decode(fields[0]));\n\n return header.kid === kmsStaticPubKey.kid;\n });\n },\n\n /**\n * Sends a request to the kms\n * @param {Object} payload\n * @param {Object} options\n * @param {Number} options.timeout (internal)\n * @param {string} options.onBehalfOf Run the request on behalf of another user (UUID), used in compliance scenarios\n * @returns {Promise<Object>}\n */\n request(payload, {timeout, onBehalfOf} = {}) {\n timeout = timeout || this.config.kmsInitialTimeout;\n\n // Note: this should only happen when we're using the async kms batcher;\n // once we implement the sync batcher, this'll need to be smarter.\n return (\n this.webex.internal.mercury\n .connect()\n .then(() => this.prepareRequest(payload, onBehalfOf))\n .then((req) => {\n req[TIMEOUT_SYMBOL] = timeout;\n\n return this.batcher.request(req);\n })\n // High complexity is due to attempt at test mode resiliency\n // eslint-disable-next-line complexity\n .catch((reason) => {\n if (\n process.env.NODE_ENV === 'test' &&\n (reason.status === 403 || reason.statusCode === 403) &&\n reason.message.match(\n /Failed to resolve authorization token in KmsMessage request for user/\n )\n ) {\n this.logger.warn('kms: rerequested key due to test-mode kms auth failure');\n\n return this.request(payload, {onBehalfOf});\n }\n\n // KMS Error. Notify the user\n if (reason instanceof KMSError) {\n this.webex.trigger('client:InvalidRequestError');\n\n return Promise.reject(reason);\n }\n\n // Ideally, most or all of the code below would go in kms-batcher, but\n // but batching needs at least one more round of refactoring for that to\n // work.\n if (!reason.statusCode && !reason.status) {\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n /* istanbul ignore next: reason.stack vs stack difficult to control in test */\n this.logger.info('kms: request error', reason.stack || reason);\n }\n\n consoleDebug(`timeout ${timeout}`);\n timeout *= 2;\n\n if (timeout >= this.config.ecdhMaxTimeout) {\n this.logger.info('kms: exceeded maximum KMS request retries');\n\n return Promise.reject(reason);\n }\n\n // Peek ahead to make sure we don't reset the timeout if the next timeout\n // will exceed the maximum timeout for renegotiating ECDH keys.\n const nextTimeout = timeout * 2;\n\n if (timeout >= this.config.kmsMaxTimeout && nextTimeout < this.config.ecdhMaxTimeout) {\n this.logger.info(\n 'kms: exceeded maximum KMS request retries; negotiating new ecdh key'\n );\n\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info('kms: timeout/maxtimeout', timeout, this.config.kmsMaxTimeout);\n }\n\n contexts.delete(this);\n timeout = 0;\n }\n\n return this.request(payload, {timeout, onBehalfOf});\n }\n\n return Promise.reject(reason);\n })\n );\n },\n\n /**\n * @private\n * @returns {Promise<string>}\n */\n _getAuthorization() {\n return this.webex.credentials.getUserToken('spark:kms').then((token) => token.access_token);\n },\n\n @oneFlight\n /**\n * @private\n * @param {String} onBehalfOf create context on behalf of another user, undefined when this is not necessary\n * @returns {Promise<Object>}\n */\n _getContext() {\n let promise = contexts.get(this);\n\n if (!promise) {\n promise = this._prepareContext();\n contexts.set(this, promise);\n promise.then((context) => {\n const expiresIn = context.ephemeralKey.expirationDate - Date.now() - 30000;\n\n safeSetTimeout(() => contexts.delete(this), expiresIn);\n });\n }\n\n return Promise.all([promise, this._getAuthorization()]).then(([context, authorization]) => {\n context.clientInfo.credential.bearer = authorization;\n\n return context;\n });\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSCluster() {\n this.logger.info('kms: retrieving KMS cluster');\n\n return this._getKMSDetails().then(({kmsCluster}) => kmsCluster);\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSDetails() {\n let details = kmsDetails.get(this);\n\n if (!details) {\n this.logger.info('kms: fetching KMS details');\n details = this.webex\n .request({\n service: 'encryption',\n resource: `/kms/${this.webex.internal.device.userId}`,\n })\n .then((res) => {\n this.logger.info('kms: fetched KMS details');\n const {body} = res;\n\n body.rsaPublicKey = JSON.parse(body.rsaPublicKey);\n\n return body;\n })\n .catch((reason) => {\n this.logger.error('kms: failed to fetch KMS details', reason);\n\n return Promise.reject(reason);\n });\n\n kmsDetails.set(this, details);\n }\n\n return details;\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSStaticPubKey() {\n this.logger.info('kms: retrieving KMS static public key');\n\n return this._getKMSDetails().then(({rsaPublicKey}) => rsaPublicKey);\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _prepareContext() {\n this.logger.info('kms: creating context');\n const context = new Context();\n\n return Promise.all([\n this._getKMSStaticPubKey().then(validateKMS(this.config.caroots)),\n this._getAuthorization(),\n ])\n .then(([kmsStaticPubKey, authorization]) => {\n context.clientInfo = {\n clientId: this.webex.internal.device.url,\n credential: {\n userId: this.webex.internal.device.userId,\n bearer: authorization,\n },\n };\n\n context.serverInfo = {\n key: kmsStaticPubKey,\n };\n\n this.logger.info('kms: creating local ephemeral key');\n\n return context.createECDHKey();\n })\n .then((localECDHKey) => {\n context.ephemeralKey = localECDHKey;\n partialContexts.set(this, context);\n\n return Promise.all([localECDHKey.asKey(), this._getKMSCluster()]);\n })\n .then(([localECDHKey, cluster]) => {\n this.logger.info('kms: submitting ephemeral key request');\n\n return this.request({\n uri: `${cluster}/ecdhe`,\n method: 'create',\n jwk: localECDHKey.toJSON(),\n });\n })\n .then((res) => {\n this.logger.info('kms: deriving final ephemeral key');\n\n return context.deriveEphemeralKey(res.key);\n })\n .then((key) => {\n context.ephemeralKey = key;\n partialContexts.delete(this);\n this.logger.info('kms: derived final ephemeral key');\n\n return context;\n })\n .catch((reason) => {\n this.logger.error('kms: failed to negotiate ephemeral key', reason);\n\n return Promise.reject(reason);\n });\n },\n\n /**\n * KMS 'retrieve' requests can be made on behalf of another user. This is useful\n * for scenarios such as eDiscovery. i.e. Where an authorized compliance officer is\n * entitled to retrieve content generated by any organisational user.\n * As the KMSContext is cached, updating it will affect separate requests. Hence when\n * making a request onBehalfOf another user create a new context for just this request.\n * However this context will be 'light' as it only needs to change one field.\n * @param {Object} originalContext - The base context to 'copy'\n * @param {String} onBehalfOf - The user specified in the new context\n * @returns {Context} A 'copy' of the existing context with a new user specified\n * @private\n */\n _contextOnBehalfOf(originalContext, onBehalfOf) {\n const context = new Context();\n\n context.clientInfo = context.clientInfo = {\n clientId: originalContext.clientInfo.clientId,\n credential: {\n userId: onBehalfOf,\n onBehalfOf, // Supports running onBehalfOf self. i.e. A CO which calls onBehalfOf with CO.id.\n bearer: originalContext.clientInfo.credential.bearer,\n },\n };\n context.serverInfo = originalContext.serverInfo;\n context.ephemeralKey = originalContext.ephemeralKey;\n\n return context;\n },\n});\n\nexport default KMS;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAIA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA;AAEA;AACA;AAAmE;AAAA;AAAA;AAEnE,IAAMA,QAAQ,GAAG,sBAAa;AAC9B,IAAMC,UAAU,GAAG,sBAAa;AAChC,IAAMC,eAAe,GAAG,sBAAa;AAErC,IAAMC,YAAY,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC;;AAE5C;AACA;AACA;AACA,IAAMC,GAAG,GAAGC,sBAAW,CAACC,MAAM,SAkY3B,IAAAC,iBAAS,EAAC;EACTC,UAAU,EAAE;IAAA,IAAEC,GAAG,QAAHA,GAAG;MAAEC,UAAU,QAAVA,UAAU;IAAA,iBAASD,GAAG,cAAIC,UAAU;EAAA;AACzD,CAAC,CAAC,UApY2B;EAC7BC,SAAS,EAAE,YAAY;EAEvBC,QAAQ,EAAE;IACRC,OAAO,EAAEC;EACX,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,OAAO,0BAA6B;IAAA;IAAA,IAA3BC,GAAG,SAAHA,GAAG;MAAEC,MAAM,SAANA,MAAM;MAAEC,GAAG,SAAHA,GAAG;MAAEC,MAAM,SAANA,MAAM;IAC/BF,MAAM,GAAGA,MAAM,IAAID,GAAG,CAACP,GAAG;IAC1BU,MAAM,GAAGA,MAAM,IAAID,GAAG,CAACT,GAAG;IAE1B,IAAI,CAACW,MAAM,CAACC,IAAI,CAAC,8BAA8B,CAAC;;IAEhD;IACA,IAAI,CAACJ,MAAM,EAAE;MACX,OAAO,iBAAQK,MAAM,CAAC,IAAIC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnE;;IAEA;IACA,IAAI,CAACJ,MAAM,EAAE;MACX,OAAO,iBAAQG,MAAM,CAAC,IAAIC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnE;IAEA,OAAO,IAAI,CAACC,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBC,WAAW,EAAET,MAAM;MACnBR,GAAG,EAAEU;IACP,CAAC,CAAC,CAACQ,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,KAAI,CAACR,MAAM,CAACC,IAAI,CAAC,4BAA4B,CAAC;MAE9C,OAAOO,GAAG,CAACV,GAAG;IAChB,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEW,cAAc,iCAAgC;IAAA;IAAA,IAA9BC,OAAO,SAAPA,OAAO;MAAEC,OAAO,SAAPA,OAAO;MAAEb,GAAG,SAAHA,GAAG;MAAEc,IAAI,SAAJA,IAAI;IACzCD,OAAO,GAAGA,OAAO,IAAI,EAAE;IACvB;IACA,IAAIC,IAAI,EAAE;MACRD,OAAO,GAAGC,IAAI,CAACC,MAAM,CAAC,UAACC,IAAI,EAAEC,CAAC,EAAK;QACjCD,IAAI,CAACE,IAAI,CAACD,CAAC,CAAC1B,GAAG,CAAC;QAEhB,OAAOyB,IAAI;MACb,CAAC,EAAEH,OAAO,CAAC;IACb;;IAEA;IACA,IAAIb,GAAG,EAAE;MACPa,OAAO,CAACK,IAAI,CAAClB,GAAG,CAACT,GAAG,CAAC;IACvB;;IAEA;IACA,IAAIsB,OAAO,CAACM,MAAM,KAAK,CAAC,EAAE;MACxB,OAAO,iBAAQf,MAAM,CAAC,IAAIC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5F;IAEA,IAAI,CAACH,MAAM,CAACC,IAAI,CAAC,wBAAwB,CAAC;IAE1C,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,YAAY;MACjBqB,OAAO,EAAPA,OAAO;MACPC,OAAO,EAAPA;IACF,CAAC,CAAC,CAACJ,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,uBAAuB,CAAC;MAEzC,OAAOO,GAAG,CAACU,QAAQ;IACrB,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,gBAAgB,mCAAkC;IAAA;IAAA,IAAhCT,OAAO,SAAPA,OAAO;MAAEU,OAAO,SAAPA,OAAO;MAAExB,GAAG,SAAHA,GAAG;MAAEC,MAAM,SAANA,MAAM;IAC7Ca,OAAO,GAAGA,OAAO,IAAI,EAAE;IACvBb,MAAM,GAAGA,MAAM,IAAID,GAAG,CAACP,GAAG;IAE1B,IAAI+B,OAAO,EAAE;MACXV,OAAO,GAAGA,OAAO,CAACW,MAAM,CAACD,OAAO,CAAC;IACnC;;IAEA;IACA,IAAIV,OAAO,CAACO,MAAM,KAAK,CAAC,EAAE;MACxB,OAAO,iBAAQf,MAAM,CAAC,IAAIC,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzF;;IAEA;IACA,IAAI,CAACN,MAAM,EAAE;MACX,OAAO,iBAAQK,MAAM,CAAC,IAAIC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnE;IAEA,IAAI,CAACH,MAAM,CAACC,IAAI,CAAC,2CAA2C,CAAC;IAE7D,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,iBAAiB;MACtBiB,WAAW,EAAET,MAAM;MACnBa,OAAO,EAAPA;IACF,CAAC,CAAC,CAACH,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,0BAA0B,CAAC;MAE5C,OAAOO,GAAG,CAACc,cAAc;IAC3B,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,kBAAkB,qCAAgB;IAAA;IAAA,IAAd3B,GAAG,SAAHA,GAAG;MAAEC,MAAM,SAANA,MAAM;IAC7BA,MAAM,GAAGA,MAAM,IAAID,GAAG,CAACP,GAAG;IAC1B;IACA,IAAI,CAACQ,MAAM,EAAE;MACX,OAAO,iBAAQK,MAAM,CAAC,IAAIC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnE;IAEA,OAAO,IAAI,CAACC,OAAO,CAAC;MAClBC,MAAM,EAAE,UAAU;MAClBhB,GAAG,YAAKQ,MAAM;IAChB,CAAC,CAAC,CAACU,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,mCAAmC,CAAC;MAErD,OAAOO,GAAG,CAACc,cAAc;IAC3B,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEE,mBAAmB,sCAAgC;IAAA;IAAA,IAA9BC,MAAM,SAANA,MAAM;MAAEC,MAAM,SAANA,MAAM;MAAE9B,GAAG,SAAHA,GAAG;MAAEC,MAAM,SAANA,MAAM;IAC9C4B,MAAM,GAAGA,MAAM,IAAIC,MAAM;IACzB7B,MAAM,GAAGA,MAAM,IAAID,GAAG,CAACP,GAAG;;IAE1B;IACA,IAAI,CAACoC,MAAM,EAAE;MACX,OAAO,iBAAQvB,MAAM,CAAC,IAAIC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChF;;IAEA;IACA,IAAI,CAACN,MAAM,EAAE;MACX,OAAO,iBAAQK,MAAM,CAAC,IAAIC,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnE;IAEA,IAAI,CAACH,MAAM,CAACC,IAAI,CAAC,+CAA+C,CAAC;IAEjE,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,YAAKQ,MAAM,6BAAmB8B,oBAAW,CAACC,SAAS,CAAC;QAACH,MAAM,EAANA;MAAM,CAAC,CAAC;IAClE,CAAC,CAAC,CAAClB,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,4BAA4B,CAAC;MAE9C,OAAOO,GAAG,CAACc,cAAc;IAC3B,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEO,iBAAiB,oCAAU;IAAA;IAAA,IAARC,KAAK,SAALA,KAAK;IACtB,IAAI,CAAC9B,MAAM,CAACC,IAAI,wBAAiB6B,KAAK,mBAAgB;;IAEtD;IACA,IAAI,CAACA,KAAK,EAAE;MACV,OAAO,iBAAQ5B,MAAM,CAAC,IAAIC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjE;IAEA,OAAO,IAAI,CAACC,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,OAAO;MACZyC,KAAK,EAALA;IACF,CAAC,CAAC,CAACvB,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,4BAA4B,CAAC;MAE9C,OAAO,iBAAQ8B,GAAG,CAACvB,GAAG,CAACI,IAAI,CAACoB,GAAG,CAAC,MAAI,CAACC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACE;AACF;AACA;AACA;AACA;AACA;EACEC,cAAc,iCAAkB;IAAA;IAAA,IAAhBC,aAAa,SAAbA,aAAa;IAC3B,IAAI,CAACnC,MAAM,CAACC,IAAI,CAAC,gCAAgC,CAAC;IAElD,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,UAAU;MAClBhB,GAAG,EAAE,YAAY;MACjB8C,aAAa,EAAbA;IACF,CAAC,CAAC,CAAC5B,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,0BAA0B,CAAC;MAE5C,OAAOO,GAAG,CAAC4B,SAAS;IACtB,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;EACE;AACF;AACA;AACA;AACA;AACA;AACA;EACEC,uBAAuB,0CAAqC;IAAA;IAAA,IAAnCF,aAAa,SAAbA,aAAa;MAAEG,iBAAiB,SAAjBA,iBAAiB;IACvD,IAAI,CAACtC,MAAM,CAACC,IAAI,CAAC,0CAA0C,CAAC;IAE5D,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,MAAM;MACX8C,aAAa,EAAbA,aAAa;MACbG,iBAAiB,EAAjBA,iBAAiB;MACjBC,SAAS,EAAEC,aAAI,CAACC,EAAE;IACpB,CAAC,CAAC,CAAClC,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,2CAA2C,CAAC;MAE7D,OAAOO,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEkC,wBAAwB,4CAAkB;IAAA;IAAA,IAAhBP,aAAa,UAAbA,aAAa;IACrC,IAAI,CAACnC,MAAM,CAACC,IAAI,CAAC,4CAA4C,CAAC;IAE9D,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,UAAU;MAClBhB,GAAG,EAAE,MAAM;MACX8C,aAAa,EAAbA,aAAa;MACbI,SAAS,EAAEC,aAAI,CAACC,EAAE;IACpB,CAAC,CAAC,CAAClC,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,MAAI,CAACR,MAAM,CAACC,IAAI,CAAC,6CAA6C,CAAC;MAE/D,OAAOO,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEmC,4BAA4B,gDAAmC;IAAA;IAAA,IAAjCC,KAAK,UAALA,KAAK;MAAEC,QAAQ,UAARA,QAAQ;MAAEV,aAAa,UAAbA,aAAa;IAC1D,IAAI,CAACnC,MAAM,CAACC,IAAI,CAAC,oDAAoD,CAAC;IAEtE,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAEuD,KAAK;MACVC,QAAQ,EAARA,QAAQ;MACRV,aAAa,EAAbA,aAAa;MACbI,SAAS,EAAEC,aAAI,CAACC,EAAE;IACpB,CAAC,CAAC,CAAClC,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,2DAA2D,EAAE4C,QAAQ,CAAC;MAEvF,OAAOrC,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEsC,2BAA2B,+CAAkB;IAAA;IAAA,IAAhBX,aAAa,UAAbA,aAAa;IACxC,IAAI,CAACnC,MAAM,CAACC,IAAI,CAAC,uDAAuD,CAAC;IAEzE,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,MAAM;MACX8C,aAAa,EAAbA,aAAa;MACbI,SAAS,EAAEC,aAAI,CAACC,EAAE;IACpB,CAAC,CAAC,CAAClC,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,gDAAgD,CAAC;MAElE,OAAOO,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEuC,kBAAkB,sCAAkB;IAAA;IAAA,IAAhBZ,aAAa,UAAbA,aAAa;IAC/B,IAAI,CAACnC,MAAM,CAACC,IAAI,CAAC,sCAAsC,CAAC;IAExD,OAAO,IAAI,CAACG,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE,SAAS;MACdwD,QAAQ,EAAE,QAAQ;MAClBV,aAAa,EAAbA,aAAa;MACbI,SAAS,EAAEC,aAAI,CAACC,EAAE;IACpB,CAAC,CAAC,CAAClC,IAAI,CAAC,UAACC,GAAG,EAAK;MACf,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,4CAA4C,CAAC;MAE9D,OAAOO,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAgBDwC,QAAQ,4BAAoB;IAAA;IAAA,IAAlB3D,GAAG,UAAHA,GAAG;MAAEC,UAAU,UAAVA,UAAU;IACvB;IACA,IAAI,CAACD,GAAG,EAAE;MACR,OAAO,iBAAQa,MAAM,CAAC,IAAIC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/D;IAEA,IAAI,CAACH,MAAM,CAACC,IAAI,CAAC,mBAAmB,CAAC;IAErC,OAAO,IAAI,CAACG,OAAO,CACjB;MACEC,MAAM,EAAE,UAAU;MAClBhB,GAAG,EAAHA;IACF,CAAC,EACD;MAACC,UAAU,EAAVA;IAAU,CAAC,CACb,CAACiB,IAAI,CAAC,UAACC,GAAG,EAAK;MACd,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,kBAAkB,CAAC;MAEpC,OAAO,OAAI,CAACgC,KAAK,CAACzB,GAAG,CAACV,GAAG,CAAC;IAC5B,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;EACEmD,IAAI,kBAAG;IACL,OAAO,IAAI,CAAC7C,OAAO,CAAC;MAClBC,MAAM,EAAE,QAAQ;MAChBhB,GAAG,EAAE;IACP,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;EACE4C,KAAK,iBAACnC,GAAG,EAAE;IACT,OAAOoD,iBAAI,CAACC,GAAG,CAAClB,KAAK,CAACnC,GAAG,CAACsD,GAAG,CAAC,CAAC7C,IAAI,CAAC,UAAC6C,GAAG,EAAK;MAC3CtD,GAAG,CAACsD,GAAG,GAAGA,GAAG;MAEb,OAAOtD,GAAG;IACZ,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;EACEuD,cAAc,0BAACC,OAAO,EAAEhE,UAAU,EAAE;IAAA;IAClC,IAAMiE,aAAa,GAAGD,OAAO,CAACjD,MAAM,KAAK,QAAQ,IAAIiD,OAAO,CAACjE,GAAG,CAACmE,QAAQ,CAAC,QAAQ,CAAC;IAEnF,OAAO,iBAAQC,OAAO,CAACF,aAAa,GAAG1E,eAAe,CAAC6E,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAACC,WAAW,EAAE,CAAC,CAACpD,IAAI,CACzF,UAACqD,OAAO,EAAK;MACX,OAAI,CAAC5D,MAAM,CAACC,IAAI,yBAAkBsD,aAAa,GAAG,eAAe,GAAG,KAAK,cAAW;MACpF,IAAMM,GAAG,GAAG,IAAIC,gBAAO,CAACR,OAAO,CAAC;MAChC,IAAIS,cAAc,GAAGH,OAAO;MAE5B,IAAItE,UAAU,EAAE;QACdyE,cAAc,GAAG,OAAI,CAACC,kBAAkB,CAACJ,OAAO,EAAEtE,UAAU,CAAC;MAC/D;MAEA,OAAOuE,GAAG,CAACI,IAAI,CAACF,cAAc,EAAE;QAACG,SAAS,EAAEX;MAAa,CAAC,CAAC,CAAChD,IAAI,CAAC,YAAM;QACrE;QACA,IAAI4D,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;UACzC,OAAI,CAACrE,MAAM,CAACC,IAAI,CACd,sBAAsB,EACtBqE,aAAI,CAACC,OAAO,CAAC,oBAAKC,IAAI,CAACC,KAAK,CAAC,wBAAeZ,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE;YAACa,KAAK,EAAE;UAAI,CAAC,CAAC,CAC9E;QACH;QAEA,OAAOb,GAAG;MACZ,CAAC,CAAC;IACJ,CAAC,CACF;EACH,CAAC;EAED;AACF;AACA;AACA;AACA;EACEc,sBAAsB,kCAACC,KAAK,EAAE;IAAA;IAC5B,IAAI,CAAC5E,MAAM,CAACC,IAAI,CAAC,2BAA2B,CAAC;IAE7C,OAAO,iBAAQ8B,GAAG,CAChB6C,KAAK,CAACC,UAAU,CAACC,WAAW,CAAC9C,GAAG,CAAC,UAAC+C,UAAU,EAAEC,KAAK;MAAA,OACjD,OAAI,CAACC,eAAe,CAACF,UAAU,CAAC,CAACxE,IAAI,CAAC,UAAC2E,aAAa,EAAK;QACvD,OAAI,CAAClF,MAAM,CAACC,IAAI,yBAAkBiF,aAAa,GAAG,OAAO,GAAG,QAAQ,cAAW;QAC/E,IAAM1E,GAAG,GAAG,IAAI2E,iBAAQ,CAACJ,UAAU,CAAC;QAEpC,OACE,iBAAQtB,OAAO,CAACyB,aAAa,GAAGrG,eAAe,CAAC6E,GAAG,CAAC,OAAI,CAAC,GAAG/E,QAAQ,CAAC+E,GAAG,CAAC,OAAI,CAAC;QAC5E;QAAA,CACCnD,IAAI,CAAC,UAACqD,OAAO;UAAA,OAAKpD,GAAG,CAAC4E,MAAM,CAACxB,OAAO,CAAC;QAAA;QACtC;QAAA,CACCrD,IAAI,CAAC,YAAM;UACV,IAAI4D,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;YACzC,OAAI,CAACrE,MAAM,CAACC,IAAI,CACd,uBAAuB,EACvBqE,aAAI,CAACC,OAAO,CAAC,oBAAKC,IAAI,CAACC,KAAK,CAAC,wBAAejE,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE;cAACkE,KAAK,EAAE;YAAI,CAAC,CAAC,CAC9E;UACH;QACF,CAAC;QACD;QAAA,CACCnE,IAAI,CAAC,YAAM;UACVqE,KAAK,CAACC,UAAU,CAACC,WAAW,CAACE,KAAK,CAAC,GAAGxE,GAAG;QAC3C,CAAC;QACD;QAAA,CACCD,IAAI,CAAC;UAAA,OAAMC,GAAG;QAAA,EAAC;MAEtB,CAAC,CAAC;IAAA,EACH,CACF,CACED,IAAI,CAAC;MAAA,OAAM,OAAI,CAACd,OAAO,CAACkF,sBAAsB,CAACC,KAAK,CAAC;IAAA,EAAC,CACtDS,KAAK,CAAC,UAACC,MAAM,EAAK;MACjB,OAAI,CAACtF,MAAM,CAACuF,KAAK,CAAC,qBAAqB,EAAED,MAAM,CAACE,KAAK,CAAC;MAEtD,OAAO,iBAAQtF,MAAM,CAACoF,MAAM,CAAC;IAC/B,CAAC,CAAC,CACD/E,IAAI,CAAC;MAAA,OAAMqE,KAAK;IAAA,EAAC;EACtB,CAAC;EAED;AACF;AACA;AACA;AACA;EACEa,iBAAiB,6BAACV,UAAU,EAAE;IAC5B,IAAMvE,GAAG,GAAG,IAAI2E,iBAAQ,CAACJ,UAAU,CAAC;IAEpC,OAAOpG,QAAQ,CACZ+E,GAAG,CAAC,IAAI,CAAC,CACTnD,IAAI,CAAC,UAACqD,OAAO;MAAA,OAAKpD,GAAG,CAAC4E,MAAM,CAACxB,OAAO,CAAC;IAAA,EAAC,CACtCrD,IAAI,CAAC;MAAA,OAAMC,GAAG,CAACkF,IAAI;IAAA,EAAC;EACzB,CAAC;EAED;AACF;AACA;AACA;AACA;EACET,eAAe,2BAACF,UAAU,EAAE;IAC1B,OAAO,IAAI,CAACY,mBAAmB,EAAE,CAACpF,IAAI,CAAC,UAACqF,eAAe,EAAK;MAC1D,IAAMC,MAAM,GAAGd,UAAU,CAACe,KAAK,CAAC,GAAG,CAAC;MAEpC,IAAID,MAAM,CAAC5E,MAAM,KAAK,CAAC,EAAE;QACvB,OAAO,KAAK;MACd;MAEA,IAAM8E,MAAM,GAAGvB,IAAI,CAACC,KAAK,CAACvB,iBAAI,CAACoB,IAAI,CAAC0B,SAAS,CAACC,MAAM,CAACJ,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;MAEhE,OAAOE,MAAM,CAACG,GAAG,KAAKN,eAAe,CAACM,GAAG;IAC3C,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;EACE9F,OAAO,mBAACkD,OAAO,EAA8B;IAAA;IAAA,iFAAJ,CAAC,CAAC;MAAzB6C,OAAO,UAAPA,OAAO;MAAE7G,UAAU,UAAVA,UAAU;IACnC6G,OAAO,GAAGA,OAAO,IAAI,IAAI,CAACC,MAAM,CAACC,iBAAiB;;IAElD;IACA;IACA,OACE,IAAI,CAACC,KAAK,CAACC,QAAQ,CAACC,OAAO,CACxBC,OAAO,EAAE,CACTlG,IAAI,CAAC;MAAA,OAAM,OAAI,CAAC8C,cAAc,CAACC,OAAO,EAAEhE,UAAU,CAAC;IAAA,EAAC,CACpDiB,IAAI,CAAC,UAACsD,GAAG,EAAK;MACbA,GAAG,CAAC6C,0BAAc,CAAC,GAAGP,OAAO;MAE7B,OAAO,OAAI,CAAC1G,OAAO,CAACW,OAAO,CAACyD,GAAG,CAAC;IAClC,CAAC;IACD;IACA;IAAA,CACCwB,KAAK,CAAC,UAACC,MAAM,EAAK;MACjB,IACEnB,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,MAAM,KAC9BiB,MAAM,CAACqB,MAAM,KAAK,GAAG,IAAIrB,MAAM,CAACsB,UAAU,KAAK,GAAG,CAAC,IACpDtB,MAAM,CAACuB,OAAO,CAACC,KAAK,CAClB,sEAAsE,CACvE,EACD;QACA,OAAI,CAAC9G,MAAM,CAAC+G,IAAI,CAAC,wDAAwD,CAAC;QAE1E,OAAO,OAAI,CAAC3G,OAAO,CAACkD,OAAO,EAAE;UAAChE,UAAU,EAAVA;QAAU,CAAC,CAAC;MAC5C;;MAEA;MACA,IAAIgG,MAAM,YAAY0B,kCAAQ,EAAE;QAC9B,OAAI,CAACV,KAAK,CAACW,OAAO,CAAC,4BAA4B,CAAC;QAEhD,OAAO,iBAAQ/G,MAAM,CAACoF,MAAM,CAAC;MAC/B;;MAEA;MACA;MACA;MACA,IAAI,CAACA,MAAM,CAACsB,UAAU,IAAI,CAACtB,MAAM,CAACqB,MAAM,EAAE;QACxC;QACA,IAAIxC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;UACzC;UACA,OAAI,CAACrE,MAAM,CAACC,IAAI,CAAC,oBAAoB,EAAEqF,MAAM,CAACE,KAAK,IAAIF,MAAM,CAAC;QAChE;QAEAxG,YAAY,mBAAYqH,OAAO,EAAG;QAClCA,OAAO,IAAI,CAAC;QAEZ,IAAIA,OAAO,IAAI,OAAI,CAACC,MAAM,CAACc,cAAc,EAAE;UACzC,OAAI,CAAClH,MAAM,CAACC,IAAI,CAAC,2CAA2C,CAAC;UAE7D,OAAO,iBAAQC,MAAM,CAACoF,MAAM,CAAC;QAC/B;;QAEA;QACA;QACA,IAAM6B,WAAW,GAAGhB,OAAO,GAAG,CAAC;QAE/B,IAAIA,OAAO,IAAI,OAAI,CAACC,MAAM,CAACgB,aAAa,IAAID,WAAW,GAAG,OAAI,CAACf,MAAM,CAACc,cAAc,EAAE;UACpF,OAAI,CAAClH,MAAM,CAACC,IAAI,CACd,qEAAqE,CACtE;;UAED;UACA,IAAIkE,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY,EAAE;YACzC,OAAI,CAACrE,MAAM,CAACC,IAAI,CAAC,yBAAyB,EAAEkG,OAAO,EAAE,OAAI,CAACC,MAAM,CAACgB,aAAa,CAAC;UACjF;UAEAzI,QAAQ,CAAC0I,MAAM,CAAC,OAAI,CAAC;UACrBlB,OAAO,GAAG,CAAC;QACb;QAEA,OAAO,OAAI,CAAC/F,OAAO,CAACkD,OAAO,EAAE;UAAC6C,OAAO,EAAPA,OAAO;UAAE7G,UAAU,EAAVA;QAAU,CAAC,CAAC;MACrD;MAEA,OAAO,iBAAQY,MAAM,CAACoF,MAAM,CAAC;IAC/B,CAAC,CAAC;EAER,CAAC;EAED;AACF;AACA;AACA;EACEgC,iBAAiB,+BAAG;IAClB,OAAO,IAAI,CAAChB,KAAK,CAACiB,WAAW,CAACC,YAAY,CAAC,WAAW,CAAC,CAACjH,IAAI,CAAC,UAACkH,KAAK;MAAA,OAAKA,KAAK,CAACC,YAAY;IAAA,EAAC;EAC7F,CAAC;EAGD;AACF;AACA;AACA;AACA;EACE/D,WAAW,yBAAG;IAAA;IACZ,IAAIgE,OAAO,GAAGhJ,QAAQ,CAAC+E,GAAG,CAAC,IAAI,CAAC;IAEhC,IAAI,CAACiE,OAAO,EAAE;MACZA,OAAO,GAAG,IAAI,CAACC,eAAe,EAAE;MAChCjJ,QAAQ,CAACkJ,GAAG,CAAC,IAAI,EAAEF,OAAO,CAAC;MAC3BA,OAAO,CAACpH,IAAI,CAAC,UAACqD,OAAO,EAAK;QACxB,IAAMkE,SAAS,GAAGlE,OAAO,CAACmE,YAAY,CAACC,cAAc,GAAG,mBAAU,GAAG,KAAK;QAE1E,IAAAC,4BAAc,EAAC;UAAA,OAAMtJ,QAAQ,CAAC0I,MAAM,CAAC,OAAI,CAAC;QAAA,GAAES,SAAS,CAAC;MACxD,CAAC,CAAC;IACJ;IAEA,OAAO,iBAAQ/F,GAAG,CAAC,CAAC4F,OAAO,EAAE,IAAI,CAACL,iBAAiB,EAAE,CAAC,CAAC,CAAC/G,IAAI,CAAC,kBAA8B;MAAA;QAA5BqD,OAAO;QAAEsE,aAAa;MACnFtE,OAAO,CAACuE,UAAU,CAACC,UAAU,CAACC,MAAM,GAAGH,aAAa;MAEpD,OAAOtE,OAAO;IAChB,CAAC,CAAC;EACJ,CAAC;EAED;AACF;AACA;AACA;EACE0E,cAAc,4BAAG;IACf,IAAI,CAACtI,MAAM,CAACC,IAAI,CAAC,6BAA6B,CAAC;IAE/C,OAAO,IAAI,CAACsI,cAAc,EAAE,CAAChI,IAAI,CAAC;MAAA,IAAEiI,UAAU,UAAVA,UAAU;MAAA,OAAMA,UAAU;IAAA,EAAC;EACjE,CAAC;EAED;AACF;AACA;AACA;EACED,cAAc,4BAAG;IAAA;IACf,IAAIE,OAAO,GAAG7J,UAAU,CAAC8E,GAAG,CAAC,IAAI,CAAC;IAElC,IAAI,CAAC+E,OAAO,EAAE;MACZ,IAAI,CAACzI,MAAM,CAACC,IAAI,CAAC,2BAA2B,CAAC;MAC7CwI,OAAO,GAAG,IAAI,CAACnC,KAAK,CACjBlG,OAAO,CAAC;QACPsI,OAAO,EAAE,YAAY;QACrBxH,QAAQ,iBAAU,IAAI,CAACoF,KAAK,CAACC,QAAQ,CAACoC,MAAM,CAACjH,MAAM;MACrD,CAAC,CAAC,CACDnB,IAAI,CAAC,UAACC,GAAG,EAAK;QACb,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,0BAA0B,CAAC;QAC5C,IAAOyF,IAAI,GAAIlF,GAAG,CAAXkF,IAAI;QAEXA,IAAI,CAACkD,YAAY,GAAGpE,IAAI,CAACC,KAAK,CAACiB,IAAI,CAACkD,YAAY,CAAC;QAEjD,OAAOlD,IAAI;MACb,CAAC,CAAC,CACDL,KAAK,CAAC,UAACC,MAAM,EAAK;QACjB,OAAI,CAACtF,MAAM,CAACuF,KAAK,CAAC,kCAAkC,EAAED,MAAM,CAAC;QAE7D,OAAO,iBAAQpF,MAAM,CAACoF,MAAM,CAAC;MAC/B,CAAC,CAAC;MAEJ1G,UAAU,CAACiJ,GAAG,CAAC,IAAI,EAAEY,OAAO,CAAC;IAC/B;IAEA,OAAOA,OAAO;EAChB,CAAC;EAED;AACF;AACA;AACA;EACE9C,mBAAmB,iCAAG;IACpB,IAAI,CAAC3F,MAAM,CAACC,IAAI,CAAC,uCAAuC,CAAC;IAEzD,OAAO,IAAI,CAACsI,cAAc,EAAE,CAAChI,IAAI,CAAC;MAAA,IAAEqI,YAAY,UAAZA,YAAY;MAAA,OAAMA,YAAY;IAAA,EAAC;EACrE,CAAC;EAED;AACF;AACA;AACA;EACEhB,eAAe,6BAAG;IAAA;IAChB,IAAI,CAAC5H,MAAM,CAACC,IAAI,CAAC,uBAAuB,CAAC;IACzC,IAAM2D,OAAO,GAAG,IAAIiF,gBAAO,EAAE;IAE7B,OAAO,iBAAQ9G,GAAG,CAAC,CACjB,IAAI,CAAC4D,mBAAmB,EAAE,CAACpF,IAAI,CAAC,IAAAuI,iCAAW,EAAC,IAAI,CAAC1C,MAAM,CAAC2C,OAAO,CAAC,CAAC,EACjE,IAAI,CAACzB,iBAAiB,EAAE,CACzB,CAAC,CACC/G,IAAI,CAAC,kBAAsC;MAAA;QAApCqF,eAAe;QAAEsC,aAAa;MACpCtE,OAAO,CAACuE,UAAU,GAAG;QACnBa,QAAQ,EAAE,OAAI,CAAC1C,KAAK,CAACC,QAAQ,CAACoC,MAAM,CAACM,GAAG;QACxCb,UAAU,EAAE;UACV1G,MAAM,EAAE,OAAI,CAAC4E,KAAK,CAACC,QAAQ,CAACoC,MAAM,CAACjH,MAAM;UACzC2G,MAAM,EAAEH;QACV;MACF,CAAC;MAEDtE,OAAO,CAACsF,UAAU,GAAG;QACnBpJ,GAAG,EAAE8F;MACP,CAAC;MAED,OAAI,CAAC5F,MAAM,CAACC,IAAI,CAAC,mCAAmC,CAAC;MAErD,OAAO2D,OAAO,CAACuF,aAAa,EAAE;IAChC,CAAC,CAAC,CACD5I,IAAI,CAAC,UAAC6I,YAAY,EAAK;MACtBxF,OAAO,CAACmE,YAAY,GAAGqB,YAAY;MACnCvK,eAAe,CAACgJ,GAAG,CAAC,OAAI,EAAEjE,OAAO,CAAC;MAElC,OAAO,iBAAQ7B,GAAG,CAAC,CAACqH,YAAY,CAACnH,KAAK,EAAE,EAAE,OAAI,CAACqG,cAAc,EAAE,CAAC,CAAC;IACnE,CAAC,CAAC,CACD/H,IAAI,CAAC,kBAA6B;MAAA;QAA3B6I,YAAY;QAAEC,OAAO;MAC3B,OAAI,CAACrJ,MAAM,CAACC,IAAI,CAAC,uCAAuC,CAAC;MAEzD,OAAO,OAAI,CAACG,OAAO,CAAC;QAClBf,GAAG,YAAKgK,OAAO,WAAQ;QACvBhJ,MAAM,EAAE,QAAQ;QAChB+C,GAAG,EAAEgG,YAAY,CAACE,MAAM;MAC1B,CAAC,CAAC;IACJ,CAAC,CAAC,CACD/I,IAAI,CAAC,UAACC,GAAG,EAAK;MACb,OAAI,CAACR,MAAM,CAACC,IAAI,CAAC,mCAAmC,CAAC;MAErD,OAAO2D,OAAO,CAAC2F,kBAAkB,CAAC/I,GAAG,CAACV,GAAG,CAAC;IAC5C,CAAC,CAAC,CACDS,IAAI,CAAC,UAACT,GAAG,EAAK;MACb8D,OAAO,CAACmE,YAAY,GAAGjI,GAAG;MAC1BjB,eAAe,CAACwI,MAAM,CAAC,OAAI,CAAC;MAC5B,OAAI,CAACrH,MAAM,CAACC,IAAI,CAAC,kCAAkC,CAAC;MAEpD,OAAO2D,OAAO;IAChB,CAAC,CAAC,CACDyB,KAAK,CAAC,UAACC,MAAM,EAAK;MACjB,OAAI,CAACtF,MAAM,CAACuF,KAAK,CAAC,wCAAwC,EAAED,MAAM,CAAC;MAEnE,OAAO,iBAAQpF,MAAM,CAACoF,MAAM,CAAC;IAC/B,CAAC,CAAC;EACN,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEtB,kBAAkB,8BAACwF,eAAe,EAAElK,UAAU,EAAE;IAC9C,IAAMsE,OAAO,GAAG,IAAIiF,gBAAO,EAAE;IAE7BjF,OAAO,CAACuE,UAAU,GAAGvE,OAAO,CAACuE,UAAU,GAAG;MACxCa,QAAQ,EAAEQ,eAAe,CAACrB,UAAU,CAACa,QAAQ;MAC7CZ,UAAU,EAAE;QACV1G,MAAM,EAAEpC,UAAU;QAClBA,UAAU,EAAVA,UAAU;QAAE;QACZ+I,MAAM,EAAEmB,eAAe,CAACrB,UAAU,CAACC,UAAU,CAACC;MAChD;IACF,CAAC;IACDzE,OAAO,CAACsF,UAAU,GAAGM,eAAe,CAACN,UAAU;IAC/CtF,OAAO,CAACmE,YAAY,GAAGyB,eAAe,CAACzB,YAAY;IAEnD,OAAOnE,OAAO;EAChB,CAAC;EAAA;AACH,CAAC,oMA3KEzE,iBAAS,+EA2KV;AAAC,eAEYH,GAAG;AAAA"}
|
|
1
|
+
{"version":3,"names":["contexts","kmsDetails","partialContexts","consoleDebug","require","KMS","WebexPlugin","extend","oneFlight","keyFactory","uri","onBehalfOf","namespace","children","batcher","KMSBatcher","bindKey","kro","kroUri","key","keyUri","logger","info","reject","Error","request","method","resourceUri","then","res","createResource","userIds","keyUris","keys","reduce","uris","k","push","length","resource","addAuthorization","authIds","concat","authorizations","listAuthorizations","removeAuthorization","authId","userId","querystring","stringify","createUnboundKeys","count","all","map","asKey","fetchPublicKey","assignedOrgId","publicKey","uploadCustomerMasterKey","customerMasterKey","awsKms","requestId","uuid","v4","listAllCustomerMasterKey","changeCustomerMasterKeyState","keyId","keyState","deleteAllCustomerMasterKeys","useGlobalMasterKey","fetchKey","ping","jose","JWK","jwk","prepareRequest","payload","isECDHRequest","includes","resolve","get","_getContext","context","req","Request","requestContext","_contextOnBehalfOf","wrap","serverKey","process","env","NODE_ENV","util","inspect","JSON","parse","depth","processKmsMessageEvent","event","encryption","kmsMessages","kmsMessage","index","_isECDHEMessage","isECDHMessage","Response","unwrap","catch","reason","error","stack","decryptKmsMessage","body","_getKMSStaticPubKey","kmsStaticPubKey","fields","split","header","base64url","decode","kid","timeout","config","kmsInitialTimeout","webex","internal","mercury","connect","TIMEOUT_SYMBOL","status","statusCode","message","match","warn","KMSError","trigger","ecdhMaxTimeout","nextTimeout","kmsMaxTimeout","delete","_getAuthorization","credentials","getUserToken","token","access_token","promise","_prepareContext","set","expiresIn","ephemeralKey","expirationDate","safeSetTimeout","authorization","clientInfo","credential","bearer","_getKMSCluster","_getKMSDetails","kmsCluster","details","service","device","rsaPublicKey","Context","validateKMS","caroots","clientId","url","serverInfo","createECDHKey","localECDHKey","cluster","toJSON","deriveEphemeralKey","originalContext"],"sources":["kms.js"],"sourcesContent":["/*!\n * Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.\n */\n\nimport querystring from 'querystring';\nimport util from 'util';\n\nimport {safeSetTimeout} from '@webex/common-timers';\nimport {oneFlight} from '@webex/common';\nimport {WebexPlugin} from '@webex/webex-core';\nimport {Context, Request, Response} from 'node-kms';\nimport jose from 'node-jose';\nimport {omit} from 'lodash';\nimport uuid from 'uuid';\n\nimport KMSBatcher, {TIMEOUT_SYMBOL} from './kms-batcher';\nimport validateKMS, {KMSError} from './kms-certificate-validation';\n\nconst contexts = new WeakMap();\nconst kmsDetails = new WeakMap();\nconst partialContexts = new WeakMap();\n\nconst consoleDebug = require('debug')('kms');\n\n/**\n * @class\n */\nconst KMS = WebexPlugin.extend({\n namespace: 'Encryption',\n\n children: {\n batcher: KMSBatcher,\n },\n\n /**\n * Binds a key to a resource\n * @param {Object} options\n * @param {KMSResourceObject} options.kro\n * @param {string} options.kroUri\n * @param {Key} options.key\n * @param {string} options.keyUri\n * @returns {Promise<Key>}\n */\n bindKey({kro, kroUri, key, keyUri}) {\n kroUri = kroUri || kro.uri;\n keyUri = keyUri || key.uri;\n\n this.logger.info('kms: binding key to resource');\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n /* istanbul ignore if */\n if (!keyUri) {\n return Promise.reject(new Error('`key` or `keyUri` is required'));\n }\n\n return this.request({\n method: 'update',\n resourceUri: kroUri,\n uri: keyUri,\n }).then((res) => {\n this.logger.info('kms: bound key to resource');\n\n return res.key;\n });\n },\n\n /**\n * Creates a new KMS Resource\n * @param {Object} options\n * @param {Array<string>} options.userIds\n * @param {Array<string>} options.keyUris\n * @param {Key} options.key\n * @param {Array<Keys>} options.keys\n * @returns {Promise<KMSResourceObject>}\n */\n createResource({userIds, keyUris, key, keys}) {\n keyUris = keyUris || [];\n /* istanbul ignore if */\n if (keys) {\n keyUris = keys.reduce((uris, k) => {\n uris.push(k.uri);\n\n return uris;\n }, keyUris);\n }\n\n /* istanbul ignore else */\n if (key) {\n keyUris.push(key.uri);\n }\n\n /* istanbul ignore if */\n if (keyUris.length === 0) {\n return Promise.reject(new Error('Cannot create KMS Resource without at least one keyUri'));\n }\n\n this.logger.info('kms: creating resource');\n\n return this.request({\n method: 'create',\n uri: '/resources',\n userIds,\n keyUris,\n }).then((res) => {\n this.logger.info('kms: created resource');\n\n return res.resource;\n });\n },\n\n /**\n * Authorizes a user or KRO to a KRO\n * @param {Object} options\n * @param {Array<string>} options.userIds\n * @param {Array<string>} options.authIds interchangable with userIds\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Promise<KMSAuthorizationObject>}\n */\n addAuthorization({userIds, authIds, kro, kroUri}) {\n userIds = userIds || [];\n kroUri = kroUri || kro.uri;\n\n if (authIds) {\n userIds = userIds.concat(authIds);\n }\n\n /* istanbul ignore if */\n if (userIds.length === 0) {\n return Promise.reject(new Error('Cannot add authorization without userIds or authIds'));\n }\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n this.logger.info('kms: adding authorization to kms resource');\n\n return this.request({\n method: 'create',\n uri: '/authorizations',\n resourceUri: kroUri,\n userIds,\n }).then((res) => {\n this.logger.info('kms: added authorization');\n\n return res.authorizations;\n });\n },\n\n /**\n * Retrieve a list of users that have been authorized to the KRO\n * @param {Object} options\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Array<authId>}\n */\n listAuthorizations({kro, kroUri}) {\n kroUri = kroUri || kro.uri;\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n return this.request({\n method: 'retrieve',\n uri: `${kroUri}/authorizations`,\n }).then((res) => {\n this.logger.info('kms: retrieved authorization list');\n\n return res.authorizations;\n });\n },\n\n /**\n * Deauthorizes a user or KRO from a KRO\n * @param {Object} options\n * @param {string} options.userId\n * @param {string} options.authId interchangable with userIds\n * @param {KMSResourceObject} options.kro the target kro\n * @param {string} options.kroUri\n * @returns {Promise<KMSAuthorizationObject>}\n */\n removeAuthorization({authId, userId, kro, kroUri}) {\n authId = authId || userId;\n kroUri = kroUri || kro.uri;\n\n /* istanbul ignore if */\n if (!authId) {\n return Promise.reject(new Error('Cannot remove authorization without authId'));\n }\n\n /* istanbul ignore if */\n if (!kroUri) {\n return Promise.reject(new Error('`kro` or `kroUri` is required'));\n }\n\n this.logger.info('kms: removing authorization from kms resource');\n\n return this.request({\n method: 'delete',\n uri: `${kroUri}/authorizations?${querystring.stringify({authId})}`,\n }).then((res) => {\n this.logger.info('kms: removed authorization');\n\n return res.authorizations;\n });\n },\n\n /**\n * Requests `count` unbound keys from the kms\n * @param {Object} options\n * @param {Number} options.count\n * @returns {Array<Key>}\n */\n createUnboundKeys({count}) {\n this.logger.info(`kms: request ${count} unbound keys`);\n\n /* istanbul ignore if */\n if (!count) {\n return Promise.reject(new Error('`options.count` is required'));\n }\n\n return this.request({\n method: 'create',\n uri: '/keys',\n count,\n }).then((res) => {\n this.logger.info('kms: received unbound keys');\n\n return Promise.all(res.keys.map(this.asKey));\n });\n },\n\n /**\n * @typedef {Object} FetchPublicKeyResponse\n * @property {number} status 200,400(Bad Request: Request payload missing info),404(Not Found: HSM Public Key not found),501(Not Implemented: This KMS does not support BYOK),502(Bad Gateway: KMS could not communicate with HSM)\n * @property {UUID} requestId this is should be unique, used for debug.\n * @property {string} publicKey\n */\n /**\n * get public key from kms\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<FetchPublicKeyResponse>} response of get public key api\n */\n fetchPublicKey({assignedOrgId}) {\n this.logger.info('kms: fetch public key for byok');\n\n return this.request({\n method: 'retrieve',\n uri: '/publicKey',\n assignedOrgId,\n }).then((res) => {\n this.logger.info('kms: received public key');\n\n return res.publicKey;\n });\n },\n\n /**\n * @typedef {Object} UploadCmkResponse\n * @property {number} status\n * @property {UUID} requestId\n * @property {string} uri\n * @property {string} keysState\n */\n /**\n * upload master key for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @param {string} options.customerMasterKey the master key\n * @param {boolean} options.awsKms enable amazon aws keys\n * @returns {Promise.<UploadCmkResponse>} response of upload CMK api\n */\n uploadCustomerMasterKey({assignedOrgId, customerMasterKey, awsKms = false}) {\n this.logger.info('kms: upload customer master key for byok');\n\n return this.request({\n method: 'create',\n uri: awsKms ? '/awsKmsCmk' : '/cmk',\n assignedOrgId,\n customerMasterKey,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to upload customer master key');\n\n return res;\n });\n },\n\n /**\n * get all customer master keys for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @param {boolean} options.awsKms enable amazon aws keys\n * @returns {Promise.<ActivateCmkResponse>} response of list CMKs api\n */\n listAllCustomerMasterKey({assignedOrgId, awsKms = false}) {\n this.logger.info('kms: get all customer master keys for byok');\n\n return this.request({\n method: 'retrieve',\n uri: awsKms ? '/awsKmsCmk' : '/cmk',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to get all customer master keys');\n\n return res;\n });\n },\n\n /**\n * @typedef {Object} ActivateCmkResponse\n * @property {number} status\n * @property {UUID} requestId\n * @property {Array<CMK>} customerMasterKeys\n */\n /**\n *\n * @typedef {Object} CMK\n * @property {string} usageState\n * @property {UUID} assignedOrgId\n * @property {string} uri\n * @property {string} source\n * @property {Date | undefined} stateUpdatedOn\n * @property {Date | undefined} rotation\n */\n /**\n * change one customer master key state for one org.\n * delete pending key, then the keyState should be 'removedclean';\n * active pending key, then the keyState should be 'active';\n *\n * @param {Object} options\n * @param {string} options.keyId the id of one customer master key, it should be a url\n * @param {string} options.keyState one of the following: PENDING, RECOVERING,ACTIVE,REVOKED,DEACTIVATED,REENCRYPTING,RETIRED,DELETED,DISABLED,REMOVEDCLEAN,REMOVEDDIRTY;\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<ActivateCmkResponse>} response of list CMKs api\n */\n changeCustomerMasterKeyState({keyId, keyState, assignedOrgId}) {\n this.logger.info('kms: change one customer master key state for byok');\n\n return this.request({\n method: 'update',\n uri: keyId,\n keyState,\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to change the customer master key state to {}', keyState);\n\n return res;\n });\n },\n\n /**\n * this is for test case. it will delete all CMKs, no matter what their status is. This is mainly for test purpose\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @param {boolean} options.awsKms enable amazon aws keys\n * @returns {Promise.<{status, requestId}>}\n */\n deleteAllCustomerMasterKeys({assignedOrgId, awsKms = false}) {\n this.logger.info('kms: delete all customer master keys at the same time');\n\n return this.request({\n method: 'delete',\n uri: awsKms ? '/awsKmsCmk' : '/cmk',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to delete all customer master keys');\n\n return res;\n });\n },\n\n /**\n * return to use global master key for one org.\n * @param {Object} options\n * @param {UUID} options.assignedOrgId the orgId\n * @returns {Promise.<ActivateCmkResponse>} response of activate CMK api\n */\n useGlobalMasterKey({assignedOrgId}) {\n this.logger.info('kms: return to use global master key');\n\n return this.request({\n method: 'update',\n uri: 'default',\n keyState: 'ACTIVE',\n assignedOrgId,\n requestId: uuid.v4(),\n }).then((res) => {\n this.logger.info('kms: finish to return to global master key');\n\n return res;\n });\n },\n\n /**\n * Fetches the specified key from the kms\n * @param {Object} options\n * @param {string} options.uri\n * @param {string} options.onBehalfOf The id of a user, upon whose behalf, the key is to be retrieved or undefined if retrieval is for the active user\n * @returns {Promise<Key>}\n */\n // Ideally, this would be done via the kms batcher, but other than request id,\n // there isn't any other userful key in a kms response to match it to a\n // request. as such, we need the batcher to group requests, but one flight to\n // make sure we don't make the same request multiple times.\n @oneFlight({\n keyFactory: ({uri, onBehalfOf}) => `${uri}/${onBehalfOf}`,\n })\n fetchKey({uri, onBehalfOf}) {\n /* istanbul ignore if */\n if (!uri) {\n return Promise.reject(new Error('`options.uri` is required'));\n }\n\n this.logger.info('kms: fetching key');\n\n return this.request(\n {\n method: 'retrieve',\n uri,\n },\n {onBehalfOf}\n ).then((res) => {\n this.logger.info('kms: fetched key');\n\n return this.asKey(res.key);\n });\n },\n\n /**\n * Pings the kms. Mostly for testing\n * @returns {Promise}\n */\n ping() {\n return this.request({\n method: 'update',\n uri: '/ping',\n });\n },\n\n /**\n * Ensures a key obect is Key instance\n * @param {Object} key\n * @returns {Promise<Key>}\n */\n asKey(key) {\n return jose.JWK.asKey(key.jwk).then((jwk) => {\n key.jwk = jwk;\n\n return key;\n });\n },\n\n /**\n * Adds appropriate metadata to the KMS request\n * @param {Object} payload\n * @param {Object} onBehalfOf Optional parameter to prepare the request on behalf of another user\n * @returns {Promise<KMS.Request>}\n */\n prepareRequest(payload, onBehalfOf) {\n const isECDHRequest = payload.method === 'create' && payload.uri.includes('/ecdhe');\n\n return Promise.resolve(isECDHRequest ? partialContexts.get(this) : this._getContext()).then(\n (context) => {\n this.logger.info(`kms: wrapping ${isECDHRequest ? 'ephemeral key' : 'kms'} request`);\n const req = new Request(payload);\n let requestContext = context;\n\n if (onBehalfOf) {\n requestContext = this._contextOnBehalfOf(context, onBehalfOf);\n }\n\n return req.wrap(requestContext, {serverKey: isECDHRequest}).then(() => {\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info(\n 'kms: request payload',\n util.inspect(omit(JSON.parse(JSON.stringify(req)), 'wrapped'), {depth: null})\n );\n }\n\n return req;\n });\n }\n );\n },\n\n /**\n * Accepts a kms message event, decrypts it, and passes it to the batcher\n * @param {Object} event\n * @returns {Promise<Object>}\n */\n processKmsMessageEvent(event) {\n this.logger.info('kms: received kms message');\n\n return Promise.all(\n event.encryption.kmsMessages.map((kmsMessage, index) =>\n this._isECDHEMessage(kmsMessage).then((isECDHMessage) => {\n this.logger.info(`kms: received ${isECDHMessage ? 'ecdhe' : 'normal'} message`);\n const res = new Response(kmsMessage);\n\n return (\n Promise.resolve(isECDHMessage ? partialContexts.get(this) : contexts.get(this))\n // eslint-disable-next-line max-nested-callbacks\n .then((context) => res.unwrap(context))\n // eslint-disable-next-line max-nested-callbacks\n .then(() => {\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info(\n 'kms: response payload',\n util.inspect(omit(JSON.parse(JSON.stringify(res)), 'wrapped'), {depth: null})\n );\n }\n })\n // eslint-disable-next-line max-nested-callbacks\n .then(() => {\n event.encryption.kmsMessages[index] = res;\n })\n // eslint-disable-next-line max-nested-callbacks\n .then(() => res)\n );\n })\n )\n )\n .then(() => this.batcher.processKmsMessageEvent(event))\n .catch((reason) => {\n this.logger.error('kms: decrypt failed', reason.stack);\n\n return Promise.reject(reason);\n })\n .then(() => event);\n },\n\n /**\n * Decrypts a kms message\n * @param {Object} kmsMessage\n * @returns {Promise<Object>}\n */\n decryptKmsMessage(kmsMessage) {\n const res = new Response(kmsMessage);\n\n return contexts\n .get(this)\n .then((context) => res.unwrap(context))\n .then(() => res.body);\n },\n\n /**\n * Determines if the kms message is an ecdhe message or a normal message\n * @param {Object} kmsMessage\n * @returns {Promise<boolean>}\n */\n _isECDHEMessage(kmsMessage) {\n return this._getKMSStaticPubKey().then((kmsStaticPubKey) => {\n const fields = kmsMessage.split('.');\n\n if (fields.length !== 3) {\n return false;\n }\n\n const header = JSON.parse(jose.util.base64url.decode(fields[0]));\n\n return header.kid === kmsStaticPubKey.kid;\n });\n },\n\n /**\n * Sends a request to the kms\n * @param {Object} payload\n * @param {Object} options\n * @param {Number} options.timeout (internal)\n * @param {string} options.onBehalfOf Run the request on behalf of another user (UUID), used in compliance scenarios\n * @returns {Promise<Object>}\n */\n request(payload, {timeout, onBehalfOf} = {}) {\n timeout = timeout || this.config.kmsInitialTimeout;\n\n // Note: this should only happen when we're using the async kms batcher;\n // once we implement the sync batcher, this'll need to be smarter.\n return (\n this.webex.internal.mercury\n .connect()\n .then(() => this.prepareRequest(payload, onBehalfOf))\n .then((req) => {\n req[TIMEOUT_SYMBOL] = timeout;\n\n return this.batcher.request(req);\n })\n // High complexity is due to attempt at test mode resiliency\n // eslint-disable-next-line complexity\n .catch((reason) => {\n if (\n process.env.NODE_ENV === 'test' &&\n (reason.status === 403 || reason.statusCode === 403) &&\n reason.message.match(\n /Failed to resolve authorization token in KmsMessage request for user/\n )\n ) {\n this.logger.warn('kms: rerequested key due to test-mode kms auth failure');\n\n return this.request(payload, {onBehalfOf});\n }\n\n // KMS Error. Notify the user\n if (reason instanceof KMSError) {\n this.webex.trigger('client:InvalidRequestError');\n\n return Promise.reject(reason);\n }\n\n // Ideally, most or all of the code below would go in kms-batcher, but\n // but batching needs at least one more round of refactoring for that to\n // work.\n if (!reason.statusCode && !reason.status) {\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n /* istanbul ignore next: reason.stack vs stack difficult to control in test */\n this.logger.info('kms: request error', reason.stack || reason);\n }\n\n consoleDebug(`timeout ${timeout}`);\n timeout *= 2;\n\n if (timeout >= this.config.ecdhMaxTimeout) {\n this.logger.info('kms: exceeded maximum KMS request retries');\n\n return Promise.reject(reason);\n }\n\n // Peek ahead to make sure we don't reset the timeout if the next timeout\n // will exceed the maximum timeout for renegotiating ECDH keys.\n const nextTimeout = timeout * 2;\n\n if (timeout >= this.config.kmsMaxTimeout && nextTimeout < this.config.ecdhMaxTimeout) {\n this.logger.info(\n 'kms: exceeded maximum KMS request retries; negotiating new ecdh key'\n );\n\n /* istanbul ignore else */\n if (process.env.NODE_ENV !== 'production') {\n this.logger.info('kms: timeout/maxtimeout', timeout, this.config.kmsMaxTimeout);\n }\n\n contexts.delete(this);\n timeout = 0;\n }\n\n return this.request(payload, {timeout, onBehalfOf});\n }\n\n return Promise.reject(reason);\n })\n );\n },\n\n /**\n * @private\n * @returns {Promise<string>}\n */\n _getAuthorization() {\n return this.webex.credentials.getUserToken('spark:kms').then((token) => token.access_token);\n },\n\n @oneFlight\n /**\n * @private\n * @param {String} onBehalfOf create context on behalf of another user, undefined when this is not necessary\n * @returns {Promise<Object>}\n */\n _getContext() {\n let promise = contexts.get(this);\n\n if (!promise) {\n promise = this._prepareContext();\n contexts.set(this, promise);\n promise.then((context) => {\n const expiresIn = context.ephemeralKey.expirationDate - Date.now() - 30000;\n\n safeSetTimeout(() => contexts.delete(this), expiresIn);\n });\n }\n\n return Promise.all([promise, this._getAuthorization()]).then(([context, authorization]) => {\n context.clientInfo.credential.bearer = authorization;\n\n return context;\n });\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSCluster() {\n this.logger.info('kms: retrieving KMS cluster');\n\n return this._getKMSDetails().then(({kmsCluster}) => kmsCluster);\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSDetails() {\n let details = kmsDetails.get(this);\n\n if (!details) {\n this.logger.info('kms: fetching KMS details');\n details = this.webex\n .request({\n service: 'encryption',\n resource: `/kms/${this.webex.internal.device.userId}`,\n })\n .then((res) => {\n this.logger.info('kms: fetched KMS details');\n const {body} = res;\n\n body.rsaPublicKey = JSON.parse(body.rsaPublicKey);\n\n return body;\n })\n .catch((reason) => {\n this.logger.error('kms: failed to fetch KMS details', reason);\n\n return Promise.reject(reason);\n });\n\n kmsDetails.set(this, details);\n }\n\n return details;\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _getKMSStaticPubKey() {\n this.logger.info('kms: retrieving KMS static public key');\n\n return this._getKMSDetails().then(({rsaPublicKey}) => rsaPublicKey);\n },\n\n /**\n * @private\n * @returns {Promise<Object>}\n */\n _prepareContext() {\n this.logger.info('kms: creating context');\n const context = new Context();\n\n return Promise.all([\n this._getKMSStaticPubKey().then(validateKMS(this.config.caroots)),\n this._getAuthorization(),\n ])\n .then(([kmsStaticPubKey, authorization]) => {\n context.clientInfo = {\n clientId: this.webex.internal.device.url,\n credential: {\n userId: this.webex.internal.device.userId,\n bearer: authorization,\n },\n };\n\n context.serverInfo = {\n key: kmsStaticPubKey,\n };\n\n this.logger.info('kms: creating local ephemeral key');\n\n return context.createECDHKey();\n })\n .then((localECDHKey) => {\n context.ephemeralKey = localECDHKey;\n partialContexts.set(this, context);\n\n return Promise.all([localECDHKey.asKey(), this._getKMSCluster()]);\n })\n .then(([localECDHKey, cluster]) => {\n this.logger.info('kms: submitting ephemeral key request');\n\n return this.request({\n uri: `${cluster}/ecdhe`,\n method: 'create',\n jwk: localECDHKey.toJSON(),\n });\n })\n .then((res) => {\n this.logger.info('kms: deriving final ephemeral key');\n\n return context.deriveEphemeralKey(res.key);\n })\n .then((key) => {\n context.ephemeralKey = key;\n partialContexts.delete(this);\n this.logger.info('kms: derived final ephemeral key');\n\n return context;\n })\n .catch((reason) => {\n this.logger.error('kms: failed to negotiate ephemeral key', reason);\n\n return Promise.reject(reason);\n });\n },\n\n /**\n * KMS 'retrieve' requests can be made on behalf of another user. This is useful\n * for scenarios such as eDiscovery. i.e. Where an authorized compliance officer is\n * entitled to retrieve content generated by any organisational user.\n * As the KMSContext is cached, updating it will affect separate requests. Hence when\n * making a request onBehalfOf another user create a new context for just this request.\n * However this context will be 'light' as it only needs to change one field.\n * @param {Object} originalContext - The base context to 'copy'\n * @param {String} onBehalfOf - The user specified in the new context\n * @returns {Context} A 'copy' of the existing context with a new user specified\n * @private\n */\n _contextOnBehalfOf(originalContext, onBehalfOf) {\n const context = new Context();\n\n context.clientInfo = context.clientInfo = {\n clientId: originalContext.clientInfo.clientId,\n credential: {\n userId: onBehalfOf,\n onBehalfOf, // Supports running onBehalfOf self. i.e. A CO which calls onBehalfOf with CO.id.\n bearer: originalContext.clientInfo.credential.bearer,\n },\n };\n context.serverInfo = originalContext.serverInfo;\n context.ephemeralKey = originalContext.ephemeralKey;\n\n return context;\n },\n});\n\nexport default KMS;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webex/internal-plugin-encryption",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.210",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,27 +24,27 @@
|
|
|
24
24
|
]
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@webex/test-helper-chai": "3.0.0-beta.
|
|
28
|
-
"@webex/test-helper-make-local-url": "3.0.0-beta.
|
|
29
|
-
"@webex/test-helper-mocha": "3.0.0-beta.
|
|
30
|
-
"@webex/test-helper-mock-webex": "3.0.0-beta.
|
|
31
|
-
"@webex/test-helper-test-users": "3.0.0-beta.
|
|
27
|
+
"@webex/test-helper-chai": "3.0.0-beta.210",
|
|
28
|
+
"@webex/test-helper-make-local-url": "3.0.0-beta.210",
|
|
29
|
+
"@webex/test-helper-mocha": "3.0.0-beta.210",
|
|
30
|
+
"@webex/test-helper-mock-webex": "3.0.0-beta.210",
|
|
31
|
+
"@webex/test-helper-test-users": "3.0.0-beta.210",
|
|
32
32
|
"sinon": "^9.2.4"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@webex/common": "3.0.0-beta.
|
|
36
|
-
"@webex/common-timers": "3.0.0-beta.
|
|
37
|
-
"@webex/http-core": "3.0.0-beta.
|
|
38
|
-
"@webex/internal-plugin-device": "3.0.0-beta.
|
|
39
|
-
"@webex/internal-plugin-encryption": "3.0.0-beta.
|
|
40
|
-
"@webex/internal-plugin-mercury": "3.0.0-beta.
|
|
41
|
-
"@webex/test-helper-file": "3.0.0-beta.
|
|
42
|
-
"@webex/webex-core": "3.0.0-beta.
|
|
35
|
+
"@webex/common": "3.0.0-beta.210",
|
|
36
|
+
"@webex/common-timers": "3.0.0-beta.210",
|
|
37
|
+
"@webex/http-core": "3.0.0-beta.210",
|
|
38
|
+
"@webex/internal-plugin-device": "3.0.0-beta.210",
|
|
39
|
+
"@webex/internal-plugin-encryption": "3.0.0-beta.210",
|
|
40
|
+
"@webex/internal-plugin-mercury": "3.0.0-beta.210",
|
|
41
|
+
"@webex/test-helper-file": "3.0.0-beta.210",
|
|
42
|
+
"@webex/webex-core": "3.0.0-beta.210",
|
|
43
43
|
"asn1js": "^2.0.26",
|
|
44
44
|
"debug": "^4.3.4",
|
|
45
45
|
"isomorphic-webcrypto": "^2.3.8",
|
|
46
46
|
"lodash": "^4.17.21",
|
|
47
|
-
"node-jose": "^2.
|
|
47
|
+
"node-jose": "^2.2.0",
|
|
48
48
|
"node-kms": "^0.4.0",
|
|
49
49
|
"node-scr": "^0.3.0",
|
|
50
50
|
"pkijs": "^2.1.84",
|
package/src/encryption.js
CHANGED
|
@@ -67,19 +67,19 @@ const Encryption = WebexPlugin.extend({
|
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Validate and initiate a Download request for requested file
|
|
70
|
-
*
|
|
70
|
+
* @param {Object} fileUrl - Plaintext
|
|
71
71
|
* @param {Object} scr - Plaintext
|
|
72
72
|
* @param {Object} options - optional parameters to download a file
|
|
73
73
|
* @returns {promise}
|
|
74
74
|
*/
|
|
75
|
-
download(scr, options) {
|
|
75
|
+
download(fileUrl, scr, options) {
|
|
76
76
|
/* istanbul ignore if */
|
|
77
|
-
if (!scr
|
|
78
|
-
return Promise.reject(new Error('`scr
|
|
77
|
+
if (!fileUrl || !scr) {
|
|
78
|
+
return Promise.reject(new Error('`scr` and `fileUrl` are required'));
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
const shunt = new EventEmitter();
|
|
82
|
-
const promise = this._fetchDownloadUrl(
|
|
82
|
+
const promise = this._fetchDownloadUrl(fileUrl, options)
|
|
83
83
|
.then((uri) => {
|
|
84
84
|
// eslint-disable-next-line no-shadow
|
|
85
85
|
const options = {
|
|
@@ -103,26 +103,25 @@ const Encryption = WebexPlugin.extend({
|
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* Fetch Download URL for the requested file
|
|
106
|
-
*
|
|
107
|
-
* @param {Object} scr - Plaintext
|
|
106
|
+
* @param {Object} fileUrl - Plaintext
|
|
108
107
|
* @param {Object} options - optional parameters to download a file
|
|
109
108
|
* @returns {promise} url of the downloadable file
|
|
110
109
|
*/
|
|
111
|
-
_fetchDownloadUrl(
|
|
110
|
+
_fetchDownloadUrl(fileUrl, options) {
|
|
112
111
|
this.logger.info('encryption: retrieving download url for encrypted file');
|
|
113
112
|
|
|
114
|
-
if (process.env.NODE_ENV !== 'production' &&
|
|
113
|
+
if (process.env.NODE_ENV !== 'production' && fileUrl.includes('localhost')) {
|
|
115
114
|
this.logger.info(
|
|
116
115
|
'encryption: bypassing webex files because this looks to be a test file on localhost'
|
|
117
116
|
);
|
|
118
117
|
|
|
119
|
-
return Promise.resolve(
|
|
118
|
+
return Promise.resolve(fileUrl);
|
|
120
119
|
}
|
|
121
120
|
|
|
122
121
|
const inputBody = {
|
|
123
|
-
endpoints: [
|
|
122
|
+
endpoints: [fileUrl],
|
|
124
123
|
};
|
|
125
|
-
const endpointUrl = url.parse(
|
|
124
|
+
const endpointUrl = url.parse(fileUrl);
|
|
126
125
|
|
|
127
126
|
// hardcode the url to use 'https' and the file service '/v1/download/endpoints' api
|
|
128
127
|
endpointUrl.protocol = 'https';
|
|
@@ -137,21 +136,29 @@ const Encryption = WebexPlugin.extend({
|
|
|
137
136
|
allow: options.params.allow,
|
|
138
137
|
}
|
|
139
138
|
: inputBody,
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
})
|
|
140
|
+
.then((res) => {
|
|
141
|
+
// eslint-disable-next-line no-shadow
|
|
142
|
+
const url = res.body.endpoints[fileUrl];
|
|
143
|
+
|
|
144
|
+
if (!url) {
|
|
145
|
+
this.logger.warn(
|
|
146
|
+
'encryption: could not determine download url for `fileUrl`; attempting to download `fileUrl` directly'
|
|
147
|
+
);
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
return fileUrl;
|
|
150
|
+
}
|
|
151
|
+
this.logger.info('encryption: retrieved download url for encrypted file');
|
|
152
|
+
|
|
153
|
+
return url;
|
|
154
|
+
})
|
|
155
|
+
.catch((err) => {
|
|
145
156
|
this.logger.warn(
|
|
146
|
-
|
|
157
|
+
`encryption: ${err} could not determine download url for ${fileUrl}; attempting to download ${fileUrl} directly`
|
|
147
158
|
);
|
|
148
159
|
|
|
149
|
-
return
|
|
150
|
-
}
|
|
151
|
-
this.logger.info('encryption: retrieved download url for encrypted file');
|
|
152
|
-
|
|
153
|
-
return url;
|
|
154
|
-
});
|
|
160
|
+
return fileUrl;
|
|
161
|
+
});
|
|
155
162
|
},
|
|
156
163
|
|
|
157
164
|
encryptBinary(file) {
|
|
@@ -29,7 +29,7 @@ const VALID_KID_PROTOCOL = 'kms:';
|
|
|
29
29
|
|
|
30
30
|
const X509_COMMON_NAME_KEY = '2.5.4.3';
|
|
31
31
|
|
|
32
|
-
const X509_SUBJECT_ALT_NAME_KEY = '2.5.29.17';
|
|
32
|
+
export const X509_SUBJECT_ALT_NAME_KEY = '2.5.29.17';
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Customize Error so the SDK knows to quit retrying and notify
|
|
@@ -101,7 +101,7 @@ const validateKidHeader = ({kid}) => {
|
|
|
101
101
|
* @throws {KMSError} if unable to validate certificate against KMS credentials
|
|
102
102
|
* @returns {void}
|
|
103
103
|
*/
|
|
104
|
-
const validateCommonName = ([certificate], {kid}) => {
|
|
104
|
+
export const validateCommonName = ([certificate], {kid}) => {
|
|
105
105
|
const kidHostname = parseUrl(kid).hostname;
|
|
106
106
|
let validationSuccessful = false;
|
|
107
107
|
|
|
@@ -112,7 +112,7 @@ const validateCommonName = ([certificate], {kid}) => {
|
|
|
112
112
|
const {altNames} = extension.parsedValue;
|
|
113
113
|
|
|
114
114
|
for (const entry of altNames) {
|
|
115
|
-
const san = entry.value;
|
|
115
|
+
const san = entry.value.toLowerCase();
|
|
116
116
|
|
|
117
117
|
validationSuccessful = san === kidHostname;
|
|
118
118
|
if (validationSuccessful) {
|
package/src/kms-errors.js
CHANGED
|
@@ -50,6 +50,14 @@ export class KmsError extends Exception {
|
|
|
50
50
|
message += `\nKMS_REQUEST_ID: ${body.requestId}`;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
if (body.statusCode) {
|
|
54
|
+
message += `\nKMS_STATUS_CODE: ${body.statusCode}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (body.errorCode) {
|
|
58
|
+
message += `\nKMS_ErrorCode: ${body.errorCode}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
53
61
|
return message;
|
|
54
62
|
}
|
|
55
63
|
}
|
package/src/kms.js
CHANGED
|
@@ -275,14 +275,15 @@ const KMS = WebexPlugin.extend({
|
|
|
275
275
|
* @param {Object} options
|
|
276
276
|
* @param {UUID} options.assignedOrgId the orgId
|
|
277
277
|
* @param {string} options.customerMasterKey the master key
|
|
278
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
278
279
|
* @returns {Promise.<UploadCmkResponse>} response of upload CMK api
|
|
279
280
|
*/
|
|
280
|
-
uploadCustomerMasterKey({assignedOrgId, customerMasterKey}) {
|
|
281
|
+
uploadCustomerMasterKey({assignedOrgId, customerMasterKey, awsKms = false}) {
|
|
281
282
|
this.logger.info('kms: upload customer master key for byok');
|
|
282
283
|
|
|
283
284
|
return this.request({
|
|
284
285
|
method: 'create',
|
|
285
|
-
uri: '/cmk',
|
|
286
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
286
287
|
assignedOrgId,
|
|
287
288
|
customerMasterKey,
|
|
288
289
|
requestId: uuid.v4(),
|
|
@@ -297,14 +298,15 @@ const KMS = WebexPlugin.extend({
|
|
|
297
298
|
* get all customer master keys for one org.
|
|
298
299
|
* @param {Object} options
|
|
299
300
|
* @param {UUID} options.assignedOrgId the orgId
|
|
301
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
300
302
|
* @returns {Promise.<ActivateCmkResponse>} response of list CMKs api
|
|
301
303
|
*/
|
|
302
|
-
listAllCustomerMasterKey({assignedOrgId}) {
|
|
304
|
+
listAllCustomerMasterKey({assignedOrgId, awsKms = false}) {
|
|
303
305
|
this.logger.info('kms: get all customer master keys for byok');
|
|
304
306
|
|
|
305
307
|
return this.request({
|
|
306
308
|
method: 'retrieve',
|
|
307
|
-
uri: '/cmk',
|
|
309
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
308
310
|
assignedOrgId,
|
|
309
311
|
requestId: uuid.v4(),
|
|
310
312
|
}).then((res) => {
|
|
@@ -361,14 +363,15 @@ const KMS = WebexPlugin.extend({
|
|
|
361
363
|
* this is for test case. it will delete all CMKs, no matter what their status is. This is mainly for test purpose
|
|
362
364
|
* @param {Object} options
|
|
363
365
|
* @param {UUID} options.assignedOrgId the orgId
|
|
366
|
+
* @param {boolean} options.awsKms enable amazon aws keys
|
|
364
367
|
* @returns {Promise.<{status, requestId}>}
|
|
365
368
|
*/
|
|
366
|
-
deleteAllCustomerMasterKeys({assignedOrgId}) {
|
|
369
|
+
deleteAllCustomerMasterKeys({assignedOrgId, awsKms = false}) {
|
|
367
370
|
this.logger.info('kms: delete all customer master keys at the same time');
|
|
368
371
|
|
|
369
372
|
return this.request({
|
|
370
373
|
method: 'delete',
|
|
371
|
-
uri: '/cmk',
|
|
374
|
+
uri: awsKms ? '/awsKmsCmk' : '/cmk',
|
|
372
375
|
assignedOrgId,
|
|
373
376
|
requestId: uuid.v4(),
|
|
374
377
|
}).then((res) => {
|
|
@@ -158,7 +158,8 @@ describe('Encryption', function () {
|
|
|
158
158
|
}));
|
|
159
159
|
});
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
// SPARK-413317
|
|
162
|
+
describe.skip('#download()', () => {
|
|
162
163
|
it('downloads and decrypts an encrypted file', () =>
|
|
163
164
|
webex.internal.encryption
|
|
164
165
|
.encryptBinary(FILE)
|
|
@@ -425,7 +425,6 @@ describe('Encryption', function () {
|
|
|
425
425
|
describe('upload customer master key', () => {
|
|
426
426
|
let uploadedkeyId;
|
|
427
427
|
|
|
428
|
-
/* eslint-disable no-unused-expressions */
|
|
429
428
|
skipInBrowser(it)('upload customer master key', () =>
|
|
430
429
|
webex.internal.encryption.kms
|
|
431
430
|
.deleteAllCustomerMasterKeys({assignedOrgId: spock.orgId})
|
|
@@ -22,18 +22,18 @@ describe('internal-plugin-encryption', () => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
describe('check _fetchDownloadUrl()', () => {
|
|
25
|
-
const
|
|
25
|
+
const fileArray = [
|
|
26
26
|
{
|
|
27
|
-
|
|
27
|
+
url: 'https://files-api-intb1.ciscospark.com/v1/spaces/a0cba376-fc05-4b88-af4b-cfffa7465f9a/contents/1d3931e7-9e31-46bc-8084-d766a8f72c99/versions/5fa9caf87a98410aae49e0173856a974/bytes',
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
|
-
|
|
30
|
+
url: 'https://files-api-intb2.ciscospark.com/v1/spaces/a0cba376-fc05-4b88-af4b-cfffa7465f9a/contents/1d3931e7-9e31-46bc-8084-d766a8f72c99/versions/5fa9caf87a98410aae49e0173856a974/bytes',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
|
|
33
|
+
url: 'https://www.test-api.com/v1/spaces/test-path-name-space/contents/test-path-name-contents/versions/test-version/bytes',
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
|
-
|
|
36
|
+
url: 'http://www.test-api.com/v1/spaces/test-path-name-space/contents/test-path-name-contents/versions/test-version/bytes',
|
|
37
37
|
},
|
|
38
38
|
];
|
|
39
39
|
const options = undefined;
|
|
@@ -44,7 +44,7 @@ describe('internal-plugin-encryption', () => {
|
|
|
44
44
|
|
|
45
45
|
spyStub = sinon.stub(webex.internal.encryption, 'request').callsFake(returnStub);
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
fileArray.forEach((file) => webex.internal.encryption._fetchDownloadUrl(file.url, options));
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it('verifying file service uris', () => {
|
|
@@ -68,10 +68,10 @@ describe('internal-plugin-encryption', () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it('verifying endpoints', () => {
|
|
71
|
-
assert.equal(spyStub.args[0][0].body.endpoints[0],
|
|
72
|
-
assert.equal(spyStub.args[1][0].body.endpoints[0],
|
|
73
|
-
assert.equal(spyStub.args[2][0].body.endpoints[0],
|
|
74
|
-
assert.equal(spyStub.args[3][0].body.endpoints[0],
|
|
71
|
+
assert.equal(spyStub.args[0][0].body.endpoints[0], fileArray[0].url);
|
|
72
|
+
assert.equal(spyStub.args[1][0].body.endpoints[0], fileArray[1].url);
|
|
73
|
+
assert.equal(spyStub.args[2][0].body.endpoints[0], fileArray[2].url);
|
|
74
|
+
assert.equal(spyStub.args[3][0].body.endpoints[0], fileArray[3].url);
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
afterEach(() => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {assert} from '@webex/test-helper-chai';
|
|
2
2
|
|
|
3
|
-
import validateCert, {KMSError} from '../../../src/kms-certificate-validation';
|
|
3
|
+
import validateCert, {KMSError, validateCommonName, X509_SUBJECT_ALT_NAME_KEY} from '../../../src/kms-certificate-validation';
|
|
4
4
|
|
|
5
5
|
const caroots = [
|
|
6
6
|
'MIID6TCCAtGgAwIBAgIURmBu688C9oUIJXlykr1J3fi5H4kwDQYJKoZIhvcNAQELBQAwgYMxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwGRGVudmVyMRAwDgYDVQQKDAdFeGFtcGxlMR8wHQYDVQQDDBZodHRwczovL2NhLmV4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTAeFw0yMDAyMDYyMDIyMDhaFw00MDAyMDEyMDIyMDhaMIGDMQswCQYDVQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEQMA4GA1UECgwHRXhhbXBsZTEfMB0GA1UEAwwWaHR0cHM6Ly9jYS5leGFtcGxlLmNvbTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7TaDWldwjU65y4fnNDIuNu4dZi3bZvaN9nJ3A8D9pwFcNx3DL5cPpafAkJuE/2ZBrsZxJWKwXLQFuNE9V3XVslv0OPgEZVfY5AKuPhVezRqEqsCdUgODMkJat6PE02r0NZRFpBiRCThh0wY5u/tiTiPgjHwEPhBEyLgcJ6FOWLn9wBsS4SvBzfppYGL5GW1G0eN9yORnKKgqkgyf0x8FvTMyVSjtkhcI/kA/8061sl4DFG6sefQmAOVvH7tp7YmN+jpQ7cOKQtjOpZS6Gp22u7LEI0/qb5n2QvjjcUQM81mN6CZ8nciWXRgjBhdAJJhmyMvcx8rnVb6vtU26fCaetAgMBAAGjUzBRMB0GA1UdDgQWBBRZiCyKaTYL94gwhxzktYg32qMOYjAfBgNVHSMEGDAWgBRZiCyKaTYL94gwhxzktYg32qMOYjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQATa2QkTGcj8IPjItnvg23ihlRjHdFHn6lB7uYPhcDurwRlBrlC2/OB44P3dHB9tEPbV4unoF9ftEKO3nNY3HUDcPrQwRqkPftlYYr4/6z/jnmNBRgiDICVaiTZNlX54fLiPsSAbIymPWLLLNtq17vjVEcfGUXhi/F+EkN/uXZ4yH6RK0YjBRwPV9cfziz1YsF2WVYVYtQErf+NTjnYR5S4Ba2kEqhI5j7mNhiafPNODaOchHcaRMvfWcBhlHt+atwNyPxNr4NP+cDjAWg0I8xAUdbZGQiRJecjkctolLHsfZXj+ulEv3eaKw7gSo3Aekexw8aZS7soy+VM1fzmLopw',
|
|
@@ -163,3 +163,36 @@ describe('internal-plugin-encryption', () => {
|
|
|
163
163
|
});
|
|
164
164
|
});
|
|
165
165
|
});
|
|
166
|
+
|
|
167
|
+
describe('validateCommonName', () => {
|
|
168
|
+
|
|
169
|
+
const checkValidate = (SAN, kidHostname) => {
|
|
170
|
+
validateCommonName(
|
|
171
|
+
[
|
|
172
|
+
{
|
|
173
|
+
extensions: [
|
|
174
|
+
{
|
|
175
|
+
extnID: X509_SUBJECT_ALT_NAME_KEY,
|
|
176
|
+
parsedValue: {
|
|
177
|
+
altNames: [{value: 'Example.com'}],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
{kid: 'https://Example.com'}
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
it('handles mixed case SAN', () => {
|
|
188
|
+
checkValidate('Example.com', 'https://Example.com');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('handles different case SAN', () => {
|
|
192
|
+
checkValidate('ExAmpLe.cOm', 'https://example.com');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('handles different case kid hostname', () => {
|
|
196
|
+
checkValidate('example.com', 'https://ExAmpLe.cOm');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2015-2020 Cisco Systems, Inc. See LICENSE file.
|
|
3
|
+
*/
|
|
4
|
+
/* eslint-disable no-underscore-dangle */
|
|
5
|
+
import Url from 'url';
|
|
6
|
+
|
|
7
|
+
import {assert} from '@webex/test-helper-chai';
|
|
8
|
+
import MockWebex from '@webex/test-helper-mock-webex';
|
|
9
|
+
import sinon from 'sinon';
|
|
10
|
+
import Encryption from '@webex/internal-plugin-encryption';
|
|
11
|
+
import {KmsError} from '../../../dist/kms-errors';
|
|
12
|
+
|
|
13
|
+
describe('internal-plugin-encryption', () => {
|
|
14
|
+
describe('kms', () => {
|
|
15
|
+
let webex;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
webex = new MockWebex({
|
|
19
|
+
children: {
|
|
20
|
+
encryption: Encryption,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('key management', () => {
|
|
26
|
+
const options = undefined;
|
|
27
|
+
let spyStub;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
const returnStub = (obj) => Promise.resolve(obj);
|
|
31
|
+
|
|
32
|
+
spyStub = sinon.stub(webex.internal.encryption.kms, 'request').callsFake(returnStub);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
spyStub.resetHistory();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('listAllCustomerMasterKey', async () => {
|
|
40
|
+
await webex.internal.encryption.kms.listAllCustomerMasterKey({
|
|
41
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
42
|
+
awsKms: false,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
await webex.internal.encryption.kms.listAllCustomerMasterKey({
|
|
46
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
47
|
+
awsKms: true,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
assert.equal(spyStub.args[0][0].uri, '/cmk');
|
|
51
|
+
assert.equal(spyStub.args[1][0].uri, '/awsKmsCmk');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('uploadCustomerMasterKey', async () => {
|
|
55
|
+
await webex.internal.encryption.kms.uploadCustomerMasterKey({
|
|
56
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
57
|
+
awsKms: false,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await webex.internal.encryption.kms.uploadCustomerMasterKey({
|
|
61
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
62
|
+
awsKms: true,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
assert.equal(spyStub.args[0][0].uri, '/cmk');
|
|
66
|
+
assert.equal(spyStub.args[1][0].uri, '/awsKmsCmk');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('deleteAllCustomerMasterKeys', async () => {
|
|
70
|
+
await webex.internal.encryption.kms.deleteAllCustomerMasterKeys({
|
|
71
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
72
|
+
awsKms: false,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await webex.internal.encryption.kms.deleteAllCustomerMasterKeys({
|
|
76
|
+
assignedOrgId: 'xx-sds-assdf',
|
|
77
|
+
awsKms: true,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
assert.equal(spyStub.args[0][0].uri, '/cmk');
|
|
81
|
+
assert.equal(spyStub.args[1][0].uri, '/awsKmsCmk');
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('KMS error', () => {
|
|
86
|
+
it('KMSError', async () => {
|
|
87
|
+
const error = new KmsError({
|
|
88
|
+
status: 404,
|
|
89
|
+
errorCode: 30005,
|
|
90
|
+
reason: 'cannot fetch keys',
|
|
91
|
+
requestId: '3434343',
|
|
92
|
+
});
|
|
93
|
+
assert.equal(
|
|
94
|
+
error.toString(),
|
|
95
|
+
'KmsError: cannot fetch keys\n' +
|
|
96
|
+
'KMS_RESPONSE_STATUS: 404\n' +
|
|
97
|
+
'KMS_REQUEST_ID: 3434343\n' +
|
|
98
|
+
'KMS_ErrorCode: 30005'
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|