Skip to content

Commit

Permalink
Merge pull request #754 from motdotla/dotenv-key-option
Browse files Browse the repository at this point in the history
Add failing test demonstrating need for DOTENV_KEY option
  • Loading branch information
motdotla committed Jun 16, 2023
2 parents 4f48954 + dacd450 commit 80219ae
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 5 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Expand Up @@ -2,7 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.2.0...master)
## [Unreleased](https://github.com/motdotla/dotenv/compare/v16.3.0...master)

## [16.3.0](https://github.com/motdotla/dotenv/compare/v16.2.0...v16.3.0) (2023-06-16)

### Added

- Optionally pass `DOTENV_KEY` to options rather than relying on `process.env.DOTENV_KEY`. Defaults to `process.env.DOTENV_KEY` [#754](https://github.com/motdotla/dotenv/pull/754)

## [16.2.0](https://github.com/motdotla/dotenv/compare/v16.1.4...v16.2.0) (2023-06-15)

Expand Down
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -339,6 +339,16 @@ console.log(myObject) // values from .env or .env.vault live here now.
console.log(process.env) // this was not changed or written to
```

##### DOTENV_KEY

Default: `process.env.DOTENV_KEY`

Pass the `DOTENV_KEY` directly to config options. Defaults to looking for `process.env.DOTENV_KEY` environment variable. Note this only applies to decrypting `.env.vault` files. If passed as null or undefined, or not passed at all, dotenv falls back to its traditional job of parsing a `.env` file.

```js
require('dotenv').config({ DOTENV_KEY: 'dotenv://:key_1234…@dotenv.org/vault/.env.vault?environment=production' })
```

### Parse

The engine which parses the contents of your file containing environment
Expand Down
2 changes: 1 addition & 1 deletion lib/cli-options.js
@@ -1,4 +1,4 @@
const re = /^dotenv_config_(encoding|path|debug|override)=(.+)$/
const re = /^dotenv_config_(encoding|path|debug|override|DOTENV_KEY)=(.+)$/

module.exports = function optionMatcher (args) {
return args.reduce(function (acc, cur) {
Expand Down
4 changes: 4 additions & 0 deletions lib/env-options.js
Expand Up @@ -17,4 +17,8 @@ if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
options.override = process.env.DOTENV_CONFIG_OVERRIDE
}

if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY
}

module.exports = options
13 changes: 10 additions & 3 deletions lib/main.js
Expand Up @@ -58,7 +58,7 @@ function _parseVault (options) {

// handle scenario for comma separated keys - for use with key rotation
// example: DOTENV_KEY="dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenv.org/vault/.env.vault?environment=prod"
const keys = _dotenvKey().split(',')
const keys = _dotenvKey(options).split(',')
const length = keys.length

let decrypted
Expand Down Expand Up @@ -99,11 +99,18 @@ function _debug (message) {
console.log(`[dotenv@${version}][DEBUG] ${message}`)
}

function _dotenvKey () {
function _dotenvKey (options) {
// prioritize developer directly setting options.DOTENV_KEY
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
return options.DOTENV_KEY
}

// secondary infra already contains a DOTENV_KEY environment variable
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
return process.env.DOTENV_KEY
}

// fallback to empty string
return ''
}

Expand Down Expand Up @@ -212,7 +219,7 @@ function config (options) {
const vaultPath = _vaultPath(options)

// fallback to original dotenv if DOTENV_KEY is not set
if (_dotenvKey().length === 0) {
if (_dotenvKey(options).length === 0) {
return DotenvModule.configDotenv(options)
}

Expand Down
14 changes: 14 additions & 0 deletions tests/test-config-vault.js
Expand Up @@ -194,6 +194,20 @@ t.test('does write over keys already in process.env if override turned on', ct =
ct.equal(process.env.ALPHA, 'zeta')
})

t.test('when DOTENV_KEY is passed as an option it successfully decrypts and injects', ct => {
envStub.restore()
envStub = sinon.stub(process.env, 'DOTENV_KEY').value('')

ct.plan(2)

const result = dotenv.config({ path: testPath, DOTENV_KEY: dotenvKey })

ct.equal(result.parsed.ALPHA, 'zeta')
ct.equal(process.env.ALPHA, 'zeta')

ct.end()
})

t.test('can write to a different object rather than process.env', ct => {
ct.plan(3)

Expand Down
6 changes: 6 additions & 0 deletions tests/test-env-options.js
Expand Up @@ -9,6 +9,7 @@ const e = process.env.DOTENV_CONFIG_ENCODING
const p = process.env.DOTENV_CONFIG_PATH
const d = process.env.DOTENV_CONFIG_DEBUG
const o = process.env.DOTENV_CONFIG_OVERRIDE
const dk = process.env.DOTENV_CONFIG_DOTENV_KEY

// get fresh object for each test
function options () {
Expand All @@ -30,6 +31,7 @@ delete process.env.DOTENV_CONFIG_ENCODING
delete process.env.DOTENV_CONFIG_PATH
delete process.env.DOTENV_CONFIG_DEBUG
delete process.env.DOTENV_CONFIG_OVERRIDE
delete process.env.DOTENV_CONFIG_DOTENV_KEY

t.same(options(), {})

Expand All @@ -45,8 +47,12 @@ testOption('DOTENV_CONFIG_DEBUG', 'true', { debug: 'true' })
// sets override option
testOption('DOTENV_CONFIG_OVERRIDE', 'true', { override: 'true' })

// sets DOTENV_KEY option
testOption('DOTENV_CONFIG_DOTENV_KEY', 'dotenv://:key_ddcaa26504cd70a@dotenv.org/vault/.env.vault?environment=development', { DOTENV_KEY: 'dotenv://:key_ddcaa26504cd70a@dotenv.org/vault/.env.vault?environment=development' })

// restore existing env
process.env.DOTENV_CONFIG_ENCODING = e
process.env.DOTENV_CONFIG_PATH = p
process.env.DOTENV_CONFIG_DEBUG = d
process.env.DOTENV_CONFIG_OVERRIDE = o
process.env.DOTENV_CONFIG_DOTENV_KEY = dk

0 comments on commit 80219ae

Please sign in to comment.