From db0efdf053cbe6b32462ccd1f3851e5df16c3771 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Fri, 16 Nov 2018 12:16:37 +0100 Subject: [PATCH] feat: trustLevel New config option replaces existing option exposeEnv. Set trustLevel=high in the bot config if you trust the contents of the repositories you are renovating. Doing so results in env being exposed, access to localhost, etc. Closes #2739 --- lib/config/cli.js | 7 ++++++- lib/config/definitions.js | 8 ++++---- lib/config/migration.js | 8 ++++++++ lib/datasource/npm.js | 8 ++++---- lib/manager/composer/artifacts.js | 2 +- lib/manager/gomod/artifacts.js | 2 +- lib/manager/npm/extract/index.js | 2 +- lib/manager/npm/post-update/index.js | 2 +- lib/workers/global/index.js | 2 +- lib/workers/repository/init/apis.js | 2 +- lib/workers/repository/init/config.js | 4 ++-- test/config/__snapshots__/migration.spec.js.snap | 2 ++ test/config/migration.spec.js | 2 ++ test/datasource/npm.spec.js | 4 ++-- website/docs/self-hosted-configuration.md | 11 +++++++++-- 15 files changed, 45 insertions(+), 21 deletions(-) diff --git a/lib/config/cli.js b/lib/config/cli.js index 086d63fa6a..454c407f86 100644 --- a/lib/config/cli.js +++ b/lib/config/cli.js @@ -17,7 +17,12 @@ function getCliName(option) { function getConfig(input) { // massage migrated configuration keys - const argv = input.map(a => a.replace('--endpoints=', '--host-rules=')); + const argv = input.map(a => + a + .replace('--endpoints=', '--host-rules=') + .replace('--expose-env=true', '--trust-level=high') + .replace('--expose-env', '--trust-level=high') + ); const options = configDefinitions.getOptions(); const config = {}; diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 94eeeeb567..75c6926a3b 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -188,12 +188,12 @@ const options = [ default: null, }, { - name: 'exposeEnv', + name: 'trustLevel', description: - 'Enable this to expose bot process.env to repositories for npmrc substitution and package installation', + 'Set this to "high" if the bot should trust the repository owners/contents', stage: 'global', - type: 'boolean', - default: false, + type: 'string', + default: 'low', }, { name: 'platform', diff --git a/lib/config/migration.js b/lib/config/migration.js index e58dcefa19..b7592e27c9 100644 --- a/lib/config/migration.js +++ b/lib/config/migration.js @@ -109,6 +109,14 @@ function migrateConfig(config) { } else if (val === false) { migratedConfig.rangeStrategy = 'replace'; } + } else if (key === 'exposeEnv') { + isMigrated = true; + delete migratedConfig.exposeEnv; + if (val === true) { + migratedConfig.trustLevel = 'high'; + } else if (val === false) { + migratedConfig.trustLevel = 'low'; + } } else if (key === 'upgradeInRange') { isMigrated = true; delete migratedConfig.upgradeInRange; diff --git a/lib/datasource/npm.js b/lib/datasource/npm.js index 4979f7940b..0673fcecc0 100644 --- a/lib/datasource/npm.js +++ b/lib/datasource/npm.js @@ -56,7 +56,7 @@ function maskToken(token) { )}${token.slice(-2)}`; } -function setNpmrc(input, exposeEnv = false) { +function setNpmrc(input, trustLevel = 'low') { if (input) { if (input === npmrcRaw) { return; @@ -73,7 +73,7 @@ function setNpmrc(input, exposeEnv = false) { delete npmrc[key]; } } - if (!exposeEnv) { + if (trustLevel !== 'high') { return; } for (const key in npmrc) { @@ -112,8 +112,8 @@ async function getPkgReleases(input, config) { return getDependency(depName, retries); } if (config) { - const exposeEnv = config.global ? config.global.exposeEnv : false; - setNpmrc(config.npmrc, exposeEnv); + const trustLevel = config.global ? config.global.trustLevel : 'low'; + setNpmrc(config.npmrc, trustLevel); } const purl = input; const res = await getDependency(purl.fullname, retries); diff --git a/lib/manager/composer/artifacts.js b/lib/manager/composer/artifacts.js index 2936a58006..9426f015d7 100644 --- a/lib/manager/composer/artifacts.js +++ b/lib/manager/composer/artifacts.js @@ -99,7 +99,7 @@ async function getArtifacts( await fs.outputFile(localAuthFileName, JSON.stringify(authJson)); } const env = - config.global && config.global.exposeEnv + config.global && config.global.trustLevel === 'high' ? process.env : { HOME: process.env.HOME, diff --git a/lib/manager/gomod/artifacts.js b/lib/manager/gomod/artifacts.js index 74c6948e63..879d5e5de2 100644 --- a/lib/manager/gomod/artifacts.js +++ b/lib/manager/gomod/artifacts.js @@ -42,7 +42,7 @@ async function getArtifacts( await fs.outputFile(localGoSumFileName, existingGoSumContent); } const env = - config.global && config.global.exposeEnv + config.global && config.global.trustLevel === 'high' ? process.env : { HOME: process.env.HOME, diff --git a/lib/manager/npm/extract/index.js b/lib/manager/npm/extract/index.js index 847d921b49..6ce36861f8 100644 --- a/lib/manager/npm/extract/index.js +++ b/lib/manager/npm/extract/index.js @@ -100,7 +100,7 @@ async function extractPackageFile(content, fileName, config) { if (npmrc) { if ( npmrc.includes('=${') && - !(config.global && config.global.exposeEnv) + !(config.global && config.global.trustLevel === 'high') ) { logger.info('Discarding .npmrc file with variables'); npmrc = undefined; diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js index 0afee7daf1..6d877f018f 100644 --- a/lib/manager/npm/post-update/index.js +++ b/lib/manager/npm/post-update/index.js @@ -345,7 +345,7 @@ async function getAdditionalFiles(config, packageFiles) { await fs.ensureDir(process.env.YARN_CACHE_FOLDER); const env = - config.global && config.global.exposeEnv + config.global && config.global.trustLevel === 'high' ? process.env : { HOME: process.env.HOME, diff --git a/lib/workers/global/index.js b/lib/workers/global/index.js index 17d814ba5f..82821326ad 100644 --- a/lib/workers/global/index.js +++ b/lib/workers/global/index.js @@ -39,7 +39,7 @@ async function start() { 'Available now for GitLab: [Renovate Pro](https://renovatebot.com/pro) with real-time webhook handling and priority job queue.'; } // Move global variables that we need to use later - const importGlobals = ['exposeEnv', 'prBanner', 'prFooter']; + const importGlobals = ['trustLevel', 'prBanner', 'prFooter']; config.global = {}; importGlobals.forEach(key => { config.global[key] = config[key]; diff --git a/lib/workers/repository/init/apis.js b/lib/workers/repository/init/apis.js index d40f1c2bd4..ebef7106c5 100644 --- a/lib/workers/repository/init/apis.js +++ b/lib/workers/repository/init/apis.js @@ -22,7 +22,7 @@ async function initApis(input) { npmApi.resetMemCache(); npmApi.setNpmrc( config.npmrc, - config.global ? config.global.exposeEnv : false + config.global ? config.global.trustLevel : 'low' ); delete config.gitPrivateKey; return config; diff --git a/lib/workers/repository/init/config.js b/lib/workers/repository/init/config.js index 7e1bfec15e..8bc2b5d238 100644 --- a/lib/workers/repository/init/config.js +++ b/lib/workers/repository/init/config.js @@ -129,7 +129,7 @@ async function mergeRenovateConfig(config) { logger.debug('Found npmrc in decrypted config - setting'); npmApi.setNpmrc( decryptedConfig.npmrc, - config.global ? config.global.exposeEnv : false + config.global ? config.global.trustLevel : 'low' ); } // Decrypt after resolving in case the preset contains npm authentication instead @@ -146,7 +146,7 @@ async function mergeRenovateConfig(config) { ); npmApi.setNpmrc( resolvedConfig.npmrc, - config.global ? config.global.exposeEnv : false + config.global ? config.global.trustLevel : 'low' ); resolvedConfig.ignoreNpmrcFile = true; } diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap index d71effdf69..85445846bb 100644 --- a/test/config/__snapshots__/migration.spec.js.snap +++ b/test/config/__snapshots__/migration.spec.js.snap @@ -32,6 +32,7 @@ Object { "automerge": true, "gitFs": "https", "schedule": "before 5am", + "trustLevel": "low", }, "major": Object { "automerge": false, @@ -130,6 +131,7 @@ Object { "travis": Object { "enabled": true, }, + "trustLevel": "high", } `; diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js index d3e695e18d..0f9b16cb84 100644 --- a/test/config/migration.spec.js +++ b/test/config/migration.spec.js @@ -57,7 +57,9 @@ describe('config/migration', () => { enabled: false, }, ], + exposeEnv: true, lockFileMaintenance: { + exposeEnv: false, gitFs: true, automerge: 'any', schedule: 'before 5am every day', diff --git a/test/datasource/npm.spec.js b/test/datasource/npm.spec.js index 8bf3afdcd8..715c4702e6 100644 --- a/test/datasource/npm.spec.js +++ b/test/datasource/npm.spec.js @@ -383,7 +383,7 @@ describe('api/npm', () => { .reply(200, npmResponse); process.env.REGISTRY = 'https://registry.from-env.com'; // eslint-disable-next-line no-template-curly-in-string - npm.setNpmrc('registry=${REGISTRY}', true); + npm.setNpmrc('registry=${REGISTRY}', 'high'); const res = await npm.getPkgReleases('foobar'); expect(res).toMatchSnapshot(); }); @@ -391,7 +391,7 @@ describe('api/npm', () => { let e; try { // eslint-disable-next-line no-template-curly-in-string - npm.setNpmrc('registry=${REGISTRY_MISSING}', true); + npm.setNpmrc('registry=${REGISTRY_MISSING}', 'high'); } catch (err) { e = err; } diff --git a/website/docs/self-hosted-configuration.md b/website/docs/self-hosted-configuration.md index ef536422bc..54ff2f2fd4 100644 --- a/website/docs/self-hosted-configuration.md +++ b/website/docs/self-hosted-configuration.md @@ -19,8 +19,6 @@ Set this to 'global' if you wish Renovate to use globally-installed binaries (`n ## endpoint -## exposeEnv - ## force This object is used as a "force override" when you need to make sure certain configuration overrides whatever is configured in the repository. For example, forcing a null (no) schedule to make sure Renovate raises PRs on a run even if the repository itself or its preset defines a schedule that's currently in active. @@ -80,4 +78,13 @@ By default, Renovate will use the most efficient approach to updating package fi ## token +## trustLevel + +Setting trustLevel to "high" can make sense in may self-hosted cases where the bot operator trusts the content in each repository. + +Setting trustLevel=high means: + +- Child processes are run with full access to `env` +- `.npmrc` files can have environment variable substitution performed + ## username -- GitLab