UNPKG

@cumulus/common

Version:
138 lines 5.78 kB
"use strict"; /** * Provides encryption and decryption methods with a consistent API but * differing mechanisms for dealing with encryption keys. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DefaultProvider = exports.S3KeyPairProvider = exports.retrieveKey = exports.getObjectStreamContents = exports.buildS3Client = exports.KMS = void 0; const node_forge_1 = __importDefault(require("node-forge")); const stream_1 = require("stream"); const client_s3_1 = require("@aws-sdk/client-s3"); const util_1 = require("./util"); const test_utils_1 = require("./test-utils"); var kms_1 = require("./kms"); Object.defineProperty(exports, "KMS", { enumerable: true, get: function () { return kms_1.KMS; } }); const getLocalStackHost = () => { if (process.env.LOCAL_S3_HOST) { return process.env.LOCAL_S3_HOST; } if (!process.env.LOCALSTACK_HOST) { throw new Error('The LOCALSTACK_HOST environment variable is not set.'); } return process.env.LOCALSTACK_HOST; }; const buildS3Client = () => { const region = process.env.AWS_DEFAULT_REGION ?? 'us-east-1'; const options = { apiVersion: '2006-03-01', region, }; if ((0, test_utils_1.inTestMode)()) { options.endpoint = `http://${getLocalStackHost()}:4566`; options.region = 'us-east-1'; options.forcePathStyle = true; options.credentials = { accessKeyId: 'my-access-key-id', secretAccessKey: 'my-secret-access-key', }; } return new client_s3_1.S3(options); }; exports.buildS3Client = buildS3Client; const getObjectStreamContents = (objectReadStream) => new Promise((resolve, reject) => { try { const responseDataChunks = []; objectReadStream.once('error', (error) => reject(error)); objectReadStream.on('data', (chunk) => responseDataChunks.push(chunk)); // Once the stream has no more data, join the chunks into a string and // return the string objectReadStream.once('end', () => resolve(responseDataChunks.join(''))); } catch (error) { reject(error); } }); exports.getObjectStreamContents = getObjectStreamContents; const getTextObject = async (bucket, key) => { const s3 = (0, exports.buildS3Client)(); const { Body } = await s3.getObject({ Bucket: bucket, Key: key, }); let data; if (Body && Body instanceof stream_1.Readable) { data = await (0, exports.getObjectStreamContents)(Body); } return data; }; const retrieveKey = async (keyId, bucket = process.env.system_bucket, stack = process.env.stackName) => { if (!bucket) { throw new Error('Unable to determine bucket to retrieve key from'); } if (!stack) { throw new Error('Unable to determine stack to retrieve key for'); } const key = `${stack}/crypto/${keyId}`; try { return await getTextObject(bucket, key); } catch (error) { throw new Error(`Failed to retrieve S3KeyPair key from s3://${bucket}/${key}: ${error.message}`); } }; exports.retrieveKey = retrieveKey; /** * Provides encryption and decryption methods using a keypair stored in S3 */ class S3KeyPairProvider { /** * Encrypt the given string using the given public key stored in the system_bucket. * * @param {string} str - The string to encrypt * @param {string} [keyId] - The name of the public key to use for encryption * @param {string} [bucket] - the optional bucket name. if not provided will * use env variable "system_bucket" * @param {stack} [stack] - the optional stack name. if not provided will * use env variable "stackName" * @returns {Promise.<string>} the encrypted string */ static async encrypt(str, keyId = 'public.pub', bucket, stack) { (0, util_1.deprecate)('@cumulus/common/key-pair-provider', '1.17.0', '@cumulus/aws-client/KMS.encrypt'); // Download the publickey const pki = node_forge_1.default.pki; const pub = await (0, exports.retrieveKey)(keyId, bucket, stack); if (!pub) { throw new Error('Unable to retrieve public key'); } const publicKey = pki.publicKeyFromPem(pub); return node_forge_1.default.util.encode64(publicKey.encrypt(str)); } /** * Decrypt the given string using a private key stored in S3 * * @param {string} str - The string to decrypt * @param {string} [keyId] - The name of the public key to use for decryption * @param {string} [bucket] - the optional bucket name. Defaults to the value * of the "system_bucket" environment variable * @param {string} [stack] - the optional stack name. Defaults to the value of * the "stackName" environment variable * @returns {Promise.<string>} the decrypted string */ static async decrypt(str, keyId = 'private.pem', bucket, stack) { (0, util_1.deprecate)('@cumulus/common/key-pair-provider', '1.17.0', '@cumulus/aws-client/KMS.decryptBase64String'); const pki = node_forge_1.default.pki; const priv = await (0, exports.retrieveKey)(keyId, bucket, stack); if (!priv) { throw new Error('Unable to retrieve private key'); } const decoded = node_forge_1.default.util.decode64(str); const privateKey = pki.privateKeyFromPem(priv); return privateKey.decrypt(decoded); } } exports.S3KeyPairProvider = S3KeyPairProvider; exports.DefaultProvider = S3KeyPairProvider; //# sourceMappingURL=key-pair-provider.js.map