UNPKG

@salesforce/plugin-release-management

Version:
123 lines 4.98 kB
"use strict"; /* * Copyright (c) 2020, salesforce.com, inc. * All rights reserved. * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ Object.defineProperty(exports, "__esModule", { value: true }); exports.signVerifyUpload = exports.getSfdxProperty = exports.SECURITY_PATH = exports.BASE_URL = void 0; /** * Signed npm packages have two fields that point plugin-trust to the URLs for the public key and signature file * see src/package.ts/#PackageJsonSfdxProperty * * This code generates a keypair using node's crypto library, * signs the tarball, * verifies the signature * and uploads the .sig and .crt (public key) to their AWS bucket * * The private key is never persisted to disk and ephemeral (exists only during this signing process) * There are no security issues returning the sig/pubKey contents because those will be public * * This verification uses the sig/crt in memory--it verifies the match before uploading. Other code verifies it from S3. * * For security reasons, the url paths and bucket are hardcoded. */ const crypto_1 = require("crypto"); const fs_1 = require("fs"); const upload_1 = require("../codeSigning/upload"); const CRYPTO_LEVEL = 'RSA-SHA256'; const BUCKET = 'dfc-data-production'; exports.BASE_URL = 'https://developer.salesforce.com'; exports.SECURITY_PATH = 'media/salesforce-cli/security'; const getSfdxProperty = (packageName, packageVersion) => { const fullPathNoExtension = `${exports.BASE_URL}/${exports.SECURITY_PATH}/${packageName}/${packageVersion}`; return { publicKeyUrl: `${fullPathNoExtension}.crt`, signatureUrl: `${fullPathNoExtension}.sig`, }; }; exports.getSfdxProperty = getSfdxProperty; const signVerifyUpload = async (signingRequest) => { const { publicKey, privateKey } = await getOneTimeUseKeys(); const { packageName, packageVersion } = signingRequest; const signatureContents = await getSignature(privateKey, signingRequest.targetFileToSign); // verify that signature/key/data worked properly await verify(signingRequest.targetFileToSign, publicKey, signatureContents); const output = { publicKeyContents: publicKey, signatureContents, packageJsonSfdxProperty: (0, exports.getSfdxProperty)(packageName, packageVersion), fileTarPath: signingRequest.targetFileToSign, packageName, packageVersion, }; if (signingRequest.upload) { await upload(output); } return output; }; exports.signVerifyUpload = signVerifyUpload; /** * Save the security items (publicKey and .sig file) to AWS based on the generates filenames */ const upload = async (input) => { return Promise.all([ // signature file (0, upload_1.putObject)(BUCKET, input.packageJsonSfdxProperty.signatureUrl.replace(`${exports.BASE_URL}/`, ''), input.signatureContents), // publicKey (0, upload_1.putObject)(BUCKET, input.packageJsonSfdxProperty.publicKeyUrl.replace(`${exports.BASE_URL}/`, ''), input.publicKeyContents), ]); }; const getOneTimeUseKeys = () => { return new Promise((resolve, reject) => { (0, crypto_1.generateKeyPair)('rsa', { modulusLength: 4096, publicKeyEncoding: { type: 'spki', format: 'pem', }, privateKeyEncoding: { type: 'pkcs8', format: 'pem', }, }, (err, publicKey, privateKey) => { if (err) reject(err); resolve({ publicKey, privateKey, }); }); }); }; const getSignature = async (privateKey, dataToSignFilePath) => { const signApi = (0, crypto_1.createSign)(CRYPTO_LEVEL); return new Promise((resolve, reject) => { const dataToSignStream = (0, fs_1.createReadStream)(dataToSignFilePath, { encoding: 'binary' }); dataToSignStream.pipe(signApi); dataToSignStream.on('end', () => { return resolve(signApi.sign(privateKey, 'base64')); }); dataToSignStream.on('error', (err) => { return reject(err); }); }); }; const verify = async (dataToSignFilePath, publicKey, signature) => { return new Promise((resolve, reject) => { const verifier = (0, crypto_1.createVerify)(CRYPTO_LEVEL); const dataToVerifyStream = (0, fs_1.createReadStream)(dataToSignFilePath, { encoding: 'binary' }); dataToVerifyStream.pipe(verifier); dataToVerifyStream.on('end', () => { if (verifier.verify(publicKey, signature, 'base64')) { return resolve(true); } return reject('The signature did not verify'); }); dataToVerifyStream.on('error', (err) => { return reject(err); }); }); }; //# sourceMappingURL=SimplifiedSigning.js.map