2019-07-17 08:14:56 +00:00
|
|
|
import is from '@sindresorhus/is';
|
|
|
|
|
2017-09-01 04:45:51 +00:00
|
|
|
const crypto = require('crypto');
|
2019-07-15 09:04:05 +00:00
|
|
|
const { logger } = require('../logger');
|
2019-01-07 05:38:24 +00:00
|
|
|
const { maskToken } = require('../util/mask');
|
2017-09-01 04:45:51 +00:00
|
|
|
|
2019-07-17 08:14:56 +00:00
|
|
|
export { decryptConfig };
|
2017-09-01 04:45:51 +00:00
|
|
|
|
2017-11-08 05:44:03 +00:00
|
|
|
function decryptConfig(config, privateKey) {
|
2018-03-27 19:57:02 +00:00
|
|
|
logger.trace({ config }, 'decryptConfig()');
|
2017-11-03 06:51:44 +00:00
|
|
|
const decryptedConfig = { ...config };
|
2017-11-10 12:46:16 +00:00
|
|
|
for (const [key, val] of Object.entries(config)) {
|
2018-06-04 18:07:22 +00:00
|
|
|
if (key === 'encrypted' && is.object(val)) {
|
2017-09-01 04:45:51 +00:00
|
|
|
logger.debug({ config: val }, 'Found encrypted config');
|
|
|
|
if (privateKey) {
|
2017-11-10 12:46:16 +00:00
|
|
|
for (const [eKey, eVal] of Object.entries(val)) {
|
2017-09-01 04:45:51 +00:00
|
|
|
try {
|
2018-08-22 09:00:19 +00:00
|
|
|
let decryptedStr;
|
|
|
|
try {
|
2019-01-24 12:41:23 +00:00
|
|
|
logger.debug('Trying default padding for ' + eKey);
|
2018-08-22 09:00:19 +00:00
|
|
|
decryptedStr = crypto
|
|
|
|
.privateDecrypt(privateKey, Buffer.from(eVal, 'base64'))
|
|
|
|
.toString();
|
2019-01-24 14:24:46 +00:00
|
|
|
logger.info('Decrypted config using default padding');
|
2018-08-22 09:00:19 +00:00
|
|
|
} catch (err) {
|
2019-01-24 12:41:23 +00:00
|
|
|
logger.debug('Trying RSA_PKCS1_PADDING for ' + eKey);
|
2018-08-22 09:00:19 +00:00
|
|
|
decryptedStr = crypto
|
|
|
|
.privateDecrypt(
|
|
|
|
{
|
|
|
|
key: privateKey,
|
|
|
|
padding: crypto.constants.RSA_PKCS1_PADDING,
|
|
|
|
},
|
|
|
|
Buffer.from(eVal, 'base64')
|
|
|
|
)
|
|
|
|
.toString();
|
|
|
|
// let it throw if the above fails
|
|
|
|
}
|
2019-01-25 05:36:07 +00:00
|
|
|
// istanbul ignore if
|
2019-01-24 12:41:23 +00:00
|
|
|
if (!decryptedStr.length) {
|
|
|
|
throw new Error('empty string');
|
|
|
|
}
|
2017-11-10 12:46:16 +00:00
|
|
|
logger.info(`Decrypted ${eKey}`);
|
|
|
|
if (eKey === 'npmToken') {
|
2018-07-03 12:45:13 +00:00
|
|
|
const token = decryptedStr.replace(/\n$/, '');
|
2018-07-03 13:05:06 +00:00
|
|
|
logger.info(
|
2019-01-24 12:19:38 +00:00
|
|
|
{ decryptedToken: maskToken(token) },
|
2018-07-03 13:05:06 +00:00
|
|
|
'Migrating npmToken to npmrc'
|
|
|
|
);
|
2018-07-05 13:44:42 +00:00
|
|
|
if (decryptedConfig.npmrc) {
|
|
|
|
/* eslint-disable no-template-curly-in-string */
|
|
|
|
if (decryptedConfig.npmrc.includes('${NPM_TOKEN}')) {
|
|
|
|
logger.debug('Replacing ${NPM_TOKEN} with decrypted token');
|
|
|
|
decryptedConfig.npmrc = decryptedConfig.npmrc.replace(
|
|
|
|
'${NPM_TOKEN}',
|
|
|
|
token
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
logger.debug(
|
|
|
|
'Appending _authToken= to end of existing npmrc'
|
|
|
|
);
|
|
|
|
decryptedConfig.npmrc = decryptedConfig.npmrc.replace(
|
|
|
|
/\n?$/,
|
|
|
|
`\n_authToken=${token}\n`
|
|
|
|
);
|
|
|
|
}
|
|
|
|
/* eslint-enable no-template-curly-in-string */
|
|
|
|
} else {
|
2018-07-06 14:56:29 +00:00
|
|
|
logger.debug('Adding npmrc to config');
|
2018-07-05 13:44:42 +00:00
|
|
|
decryptedConfig.npmrc = `//registry.npmjs.org/:_authToken=${token}\n`;
|
|
|
|
}
|
2017-09-01 05:43:49 +00:00
|
|
|
} else {
|
2017-11-10 12:46:16 +00:00
|
|
|
decryptedConfig[eKey] = decryptedStr;
|
2017-09-01 05:43:49 +00:00
|
|
|
}
|
2017-09-01 04:45:51 +00:00
|
|
|
} catch (err) {
|
2017-11-10 12:46:16 +00:00
|
|
|
logger.warn({ err }, `Error decrypting ${eKey}`);
|
2017-09-01 04:45:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
logger.error('Found encrypted data but no privateKey');
|
|
|
|
}
|
|
|
|
delete decryptedConfig.encrypted;
|
2018-06-04 18:07:22 +00:00
|
|
|
} else if (is.array(val)) {
|
2017-09-01 04:45:51 +00:00
|
|
|
decryptedConfig[key] = [];
|
|
|
|
val.forEach(item => {
|
2018-06-04 18:07:22 +00:00
|
|
|
if (is.object(item) && !is.array(item)) {
|
2017-11-08 05:44:03 +00:00
|
|
|
decryptedConfig[key].push(decryptConfig(item, privateKey));
|
2017-09-01 04:45:51 +00:00
|
|
|
} else {
|
|
|
|
decryptedConfig[key].push(item);
|
|
|
|
}
|
|
|
|
});
|
2018-06-04 18:07:22 +00:00
|
|
|
} else if (is.object(val) && key !== 'content') {
|
|
|
|
decryptedConfig[key] = decryptConfig(val, privateKey);
|
2017-09-01 04:45:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
delete decryptedConfig.encrypted;
|
2017-09-01 05:43:49 +00:00
|
|
|
logger.trace({ config: decryptedConfig }, 'decryptedConfig');
|
2017-09-01 04:45:51 +00:00
|
|
|
return decryptedConfig;
|
|
|
|
}
|