diff --git a/lib/config/admin.ts b/lib/config/admin.ts index 1bbb4b2ae8db757aa8a3e0b511dca5f9de10e677..3a112756b2502ddedfecfd027d34db0118cdb596 100644 --- a/lib/config/admin.ts +++ b/lib/config/admin.ts @@ -8,6 +8,7 @@ export const repoAdminOptions = [ 'allowedPostUpgradeCommands', 'dockerImagePrefix', 'dockerUser', + 'privateKey', 'trustLevel', ]; diff --git a/lib/config/common.ts b/lib/config/common.ts index 0de0c43d63f7327be8836c3358f6ad2c2571ecf1..687012e5bc7ffc6c68ccf4f6676b271c55f14033 100644 --- a/lib/config/common.ts +++ b/lib/config/common.ts @@ -86,6 +86,7 @@ export interface RepoAdminConfig { allowedPostUpgradeCommands?: string[]; dockerImagePrefix?: string; dockerUser?: string; + privateKey?: string | Buffer; trustLevel?: 'low' | 'high'; } @@ -113,7 +114,6 @@ export interface RenovateAdminConfig { platform?: string; postUpdateOptions?: string[]; - privateKey?: string | Buffer; requireConfig?: boolean; } diff --git a/lib/config/decrypt.spec.ts b/lib/config/decrypt.spec.ts index d3fe1a4f9881377f944cfd5d061a49d8e5f7d2ba..3910758dac8a278e74f83c2e1ef5c57fe9e579ec 100644 --- a/lib/config/decrypt.spec.ts +++ b/lib/config/decrypt.spec.ts @@ -1,4 +1,5 @@ import fs from 'fs'; +import { setAdminConfig } from './admin'; import { decryptConfig } from './decrypt'; import { RenovateConfig } from '.'; @@ -9,6 +10,7 @@ describe('config/decrypt', () => { let config: RenovateConfig; beforeEach(() => { config = {}; + setAdminConfig(); }); it('returns empty with no privateKey', () => { delete config.encrypted; @@ -23,26 +25,24 @@ describe('config/decrypt', () => { }); it('handles invalid encrypted type', () => { config.encrypted = 1; - config.privateKey = privateKey; - const res = decryptConfig(config, privateKey); + setAdminConfig({ privateKey }); + const res = decryptConfig(config); expect(res.encrypted).not.toBeDefined(); }); it('handles invalid encrypted value', () => { config.encrypted = { a: 1 }; - config.privateKey = privateKey; - expect(() => decryptConfig(config, privateKey)).toThrow( - Error('config-validation') - ); + setAdminConfig({ privateKey }); + expect(() => decryptConfig(config)).toThrow(Error('config-validation')); }); it('replaces npm token placeholder in npmrc', () => { - config.privateKey = privateKey; + setAdminConfig({ privateKey }); config.npmrc = '//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n'; // eslint-disable-line no-template-curly-in-string config.encrypted = { npmToken: 'FLA9YHIzpE7YetAg/P0X46npGRCMqn7hgyzwX5ZQ9wYgu9BRRbTiBVsUIFTyM5BuP1Q22slT2GkWvFvum7GU236Y6QiT7Nr8SLvtsJn2XUuq8H7REFKzdy3+wqyyWbCErYTFyY1dcPM7Ht+CaGDWdd8u/FsoX7AdMRs/X1jNUo6iSmlUiyGlYDKF+QMnCJom1VPVgZXWsGKdjI2MLny991QMaiv0VajmFIh4ENv4CtXOl/1twvIl/6XTXAaqpJJKDTPZEuydi+PHDZmal2RAOfrkH4m0UURa7SlfpUlIg+EaqbNGp85hCYXLwRcEET1OnYr3rH1oYkcYJ40any1tvQ==', }; - const res = decryptConfig(config, privateKey); + const res = decryptConfig(config); expect(res.encrypted).not.toBeDefined(); expect(res.npmToken).not.toBeDefined(); expect(res.npmrc).toEqual( @@ -50,19 +50,19 @@ describe('config/decrypt', () => { ); }); it('appends npm token in npmrc', () => { - config.privateKey = privateKey; + setAdminConfig({ privateKey }); config.npmrc = 'foo=bar\n'; // eslint-disable-line no-template-curly-in-string config.encrypted = { npmToken: 'FLA9YHIzpE7YetAg/P0X46npGRCMqn7hgyzwX5ZQ9wYgu9BRRbTiBVsUIFTyM5BuP1Q22slT2GkWvFvum7GU236Y6QiT7Nr8SLvtsJn2XUuq8H7REFKzdy3+wqyyWbCErYTFyY1dcPM7Ht+CaGDWdd8u/FsoX7AdMRs/X1jNUo6iSmlUiyGlYDKF+QMnCJom1VPVgZXWsGKdjI2MLny991QMaiv0VajmFIh4ENv4CtXOl/1twvIl/6XTXAaqpJJKDTPZEuydi+PHDZmal2RAOfrkH4m0UURa7SlfpUlIg+EaqbNGp85hCYXLwRcEET1OnYr3rH1oYkcYJ40any1tvQ==', }; - const res = decryptConfig(config, privateKey); + const res = decryptConfig(config); expect(res.encrypted).not.toBeDefined(); expect(res.npmToken).not.toBeDefined(); expect(res.npmrc).toMatchSnapshot(); }); it('decrypts nested', () => { - config.privateKey = privateKey; + setAdminConfig({ privateKey }); config.packageFiles = [ { packageFile: 'package.json', @@ -77,7 +77,7 @@ describe('config/decrypt', () => { }, 'backend/package.json', ]; - const res = decryptConfig(config, privateKey); + const res = decryptConfig(config); expect(res.encrypted).not.toBeDefined(); expect(res.packageFiles[0].devDependencies.encrypted).not.toBeDefined(); expect(res.packageFiles[0].devDependencies.branchPrefix).toEqual( diff --git a/lib/config/decrypt.ts b/lib/config/decrypt.ts index 9d0af983cdccf2cbe371f29f46d8a71908117ef2..639a400d28e225bd7e14a6acc341bd3bc724be08 100644 --- a/lib/config/decrypt.ts +++ b/lib/config/decrypt.ts @@ -3,14 +3,13 @@ import is from '@sindresorhus/is'; import { logger } from '../logger'; import { maskToken } from '../util/mask'; import { add } from '../util/sanitize'; +import { getAdminConfig } from './admin'; import { RenovateConfig } from './common'; -export function decryptConfig( - config: RenovateConfig, - privateKey?: string | Buffer -): RenovateConfig { +export function decryptConfig(config: RenovateConfig): RenovateConfig { logger.trace({ config }, 'decryptConfig()'); const decryptedConfig = { ...config }; + const { privateKey } = getAdminConfig(); for (const [key, val] of Object.entries(config)) { if (key === 'encrypted' && is.object(val)) { logger.debug({ config: val }, 'Found encrypted config'); @@ -90,14 +89,14 @@ export function decryptConfig( val.forEach((item) => { if (is.object(item) && !is.array(item)) { (decryptedConfig[key] as RenovateConfig[]).push( - decryptConfig(item as RenovateConfig, privateKey) + decryptConfig(item as RenovateConfig) ); } else { (decryptedConfig[key] as unknown[]).push(item); } }); } else if (is.object(val) && key !== 'content') { - decryptedConfig[key] = decryptConfig(val as RenovateConfig, privateKey); + decryptedConfig[key] = decryptConfig(val as RenovateConfig); } } delete decryptedConfig.encrypted; diff --git a/lib/workers/repository/init/config.ts b/lib/workers/repository/init/config.ts index ab3f6380916bd9cfde353e3752799203ba5092c3..47514740545d69eec251614e981d82aca3892918 100644 --- a/lib/workers/repository/init/config.ts +++ b/lib/workers/repository/init/config.ts @@ -179,7 +179,7 @@ export async function mergeRenovateConfig( delete migratedConfig.warnings; logger.debug({ config: migratedConfig }, 'migrated config'); // Decrypt before resolving in case we need npm authentication for any presets - const decryptedConfig = decryptConfig(migratedConfig, config.privateKey); + const decryptedConfig = decryptConfig(migratedConfig); // istanbul ignore if if (decryptedConfig.npmrc) { logger.debug('Found npmrc in decrypted config - setting'); @@ -187,10 +187,8 @@ export async function mergeRenovateConfig( } // Decrypt after resolving in case the preset contains npm authentication instead const resolvedConfig = decryptConfig( - await presets.resolveConfigPresets(decryptedConfig, config), - config.privateKey + await presets.resolveConfigPresets(decryptedConfig, config) ); - delete resolvedConfig.privateKey; logger.trace({ config: resolvedConfig }, 'resolved config'); // istanbul ignore if if (resolvedConfig.npmrc) {