@dotenvx/dotenvx 1.19.3 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/cli/actions/decrypt.js +25 -30
- package/src/cli/actions/encrypt.js +29 -32
- package/src/cli/actions/set.js +24 -27
- package/src/cli/dotenvx.js +15 -8
- package/src/lib/helpers/catchAndLog.js +16 -0
- package/src/lib/helpers/decryptValue.js +4 -2
- package/src/lib/helpers/determineEnvs.js +65 -0
- package/src/lib/helpers/dotenvPrivateKeyNames.js +7 -0
- package/src/lib/helpers/findPrivateKey.js +33 -0
- package/src/lib/helpers/findPublicKey.js +33 -0
- package/src/lib/helpers/isEncrypted.js +1 -1
- package/src/lib/helpers/isFullyEncrypted.js +1 -1
- package/src/lib/main.js +0 -21
- package/src/lib/services/decrypt.js +86 -81
- package/src/lib/services/encrypt.js +164 -93
- package/src/lib/services/run.js +5 -89
- package/src/lib/services/sets.js +155 -72
- package/src/shared/colors.js +6 -2
- package/src/shared/logger.js +1 -1
- package/src/lib/helpers/findOrCreatePublicKey.js +0 -94
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
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.
|
|
4
4
|
|
|
5
|
-
## [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.
|
|
5
|
+
## [Unreleased](https://github.com/dotenvx/dotenvx/compare/v1.20.0...main)
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
* respect `process.env.DOTENV_PRIVATE_KEY` and/or `process.env.DOTENV_PUBLIC_KEY` on `set` ([#401](https://github.com/dotenvx/dotenvx/pull/401))
|
|
10
|
+
* respect `process.env.DOTENV_PRIVATE_KEY` and/or `process.env.DOTENV_PUBLIC_KEY` on `encrypt` ([#411](https://github.com/dotenvx/dotenvx/pull/411))
|
|
11
|
+
* respect `process.env.DOTENV_PRIVATE_KEY` on `decrypt` ([#412](https://github.com/dotenvx/dotenvx/pull/412))
|
|
12
|
+
* change `logger.help` to use brighter blue ([#414](https://github.com/dotenvx/dotenvx/pull/414))
|
|
13
|
+
|
|
14
|
+
### Removed
|
|
15
|
+
|
|
16
|
+
* remove `main.decrypt,encrypt,set` ([#410](https://github.com/dotenvx/dotenvx/pull/410))
|
|
6
17
|
|
|
7
18
|
## 1.19.3
|
|
8
19
|
|
package/README.md
CHANGED
|
@@ -1790,7 +1790,7 @@ That said, the `.env.vault` tooling will still stick around for at least 1 year
|
|
|
1790
1790
|
|
|
1791
1791
|
#### How do I migrate my `.env.vault` file(s) to encrypted `.env` files?
|
|
1792
1792
|
|
|
1793
|
-
Run `$ dotenvx vault migrate` and follow the instructions.
|
|
1793
|
+
Run `$ dotenvx ext vault migrate` and follow the instructions.
|
|
1794
1794
|
|
|
1795
1795
|
|
|
1796
1796
|
|
package/package.json
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const Decrypt = require('./../../lib/services/decrypt')
|
|
5
|
+
|
|
6
|
+
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
5
7
|
|
|
6
8
|
function decrypt () {
|
|
7
9
|
const options = this.opts()
|
|
8
10
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
9
11
|
|
|
12
|
+
const envs = this.envs
|
|
13
|
+
|
|
10
14
|
let errorCount = 0
|
|
11
15
|
|
|
12
16
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
13
17
|
if (options.stdout) {
|
|
14
18
|
const {
|
|
15
|
-
|
|
16
|
-
} =
|
|
19
|
+
processedEnvs
|
|
20
|
+
} = new Decrypt(envs, options.key, options.excludeKey).run()
|
|
17
21
|
|
|
18
|
-
for (const
|
|
19
|
-
if (
|
|
22
|
+
for (const processedEnv of processedEnvs) {
|
|
23
|
+
if (processedEnv.error) {
|
|
20
24
|
errorCount += 1
|
|
21
|
-
console.error(
|
|
25
|
+
console.error(processedEnv.error.message)
|
|
22
26
|
} else {
|
|
23
|
-
console.log(
|
|
27
|
+
console.log(processedEnv.envSrc)
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -32,29 +36,29 @@ function decrypt () {
|
|
|
32
36
|
} else {
|
|
33
37
|
try {
|
|
34
38
|
const {
|
|
35
|
-
|
|
39
|
+
processedEnvs,
|
|
36
40
|
changedFilepaths,
|
|
37
41
|
unchangedFilepaths
|
|
38
|
-
} =
|
|
42
|
+
} = new Decrypt(envs, options.key, options.excludeKey).run()
|
|
39
43
|
|
|
40
|
-
for (const
|
|
41
|
-
logger.verbose(`decrypting ${
|
|
44
|
+
for (const processedEnv of processedEnvs) {
|
|
45
|
+
logger.verbose(`decrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
42
46
|
|
|
43
|
-
if (
|
|
47
|
+
if (processedEnv.error) {
|
|
44
48
|
errorCount += 1
|
|
45
49
|
|
|
46
|
-
if (
|
|
47
|
-
logger.error(
|
|
48
|
-
logger.help(`? add one with [echo "HELLO=World" > ${
|
|
50
|
+
if (processedEnv.error.code === 'MISSING_ENV_FILE') {
|
|
51
|
+
logger.error(processedEnv.error.message)
|
|
52
|
+
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx decrypt]`)
|
|
49
53
|
} else {
|
|
50
|
-
logger.error(
|
|
54
|
+
logger.error(processedEnv.error.message)
|
|
51
55
|
}
|
|
52
|
-
} else if (
|
|
53
|
-
fsx.writeFileX(
|
|
56
|
+
} else if (processedEnv.changed) {
|
|
57
|
+
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
54
58
|
|
|
55
|
-
logger.verbose(`decrypted ${
|
|
59
|
+
logger.verbose(`decrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
56
60
|
} else {
|
|
57
|
-
logger.verbose(`no changes ${
|
|
61
|
+
logger.verbose(`no changes ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -70,16 +74,7 @@ function decrypt () {
|
|
|
70
74
|
process.exit(1)
|
|
71
75
|
}
|
|
72
76
|
} catch (error) {
|
|
73
|
-
|
|
74
|
-
if (error.help) {
|
|
75
|
-
logger.help(error.help)
|
|
76
|
-
}
|
|
77
|
-
if (error.debug) {
|
|
78
|
-
logger.debug(error.debug)
|
|
79
|
-
}
|
|
80
|
-
if (error.code) {
|
|
81
|
-
logger.debug(`ERROR_CODE: ${error.code}`)
|
|
82
|
-
}
|
|
77
|
+
catchAndLog(error)
|
|
83
78
|
process.exit(1)
|
|
84
79
|
}
|
|
85
80
|
}
|
|
@@ -1,47 +1,53 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const Encrypt = require('./../../lib/services/encrypt')
|
|
5
5
|
|
|
6
|
+
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
6
7
|
const isIgnoringDotenvKeys = require('../../lib/helpers/isIgnoringDotenvKeys')
|
|
7
8
|
|
|
8
9
|
function encrypt () {
|
|
9
10
|
const options = this.opts()
|
|
10
11
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
12
|
|
|
13
|
+
const envs = this.envs
|
|
14
|
+
|
|
12
15
|
// stdout - should not have a try so that exit codes can surface to stdout
|
|
13
16
|
if (options.stdout) {
|
|
14
17
|
const {
|
|
15
|
-
|
|
16
|
-
} =
|
|
18
|
+
processedEnvs
|
|
19
|
+
} = new Encrypt(envs, options.key, options.excludeKey).run()
|
|
17
20
|
|
|
18
|
-
for (const
|
|
19
|
-
console.log(
|
|
21
|
+
for (const processedEnv of processedEnvs) {
|
|
22
|
+
console.log(processedEnv.envSrc)
|
|
20
23
|
}
|
|
21
24
|
process.exit(0) // exit early
|
|
22
25
|
} else {
|
|
23
26
|
try {
|
|
24
27
|
const {
|
|
25
|
-
|
|
28
|
+
processedEnvs,
|
|
26
29
|
changedFilepaths,
|
|
27
30
|
unchangedFilepaths
|
|
28
|
-
} =
|
|
31
|
+
} = new Encrypt(envs, options.key, options.excludeKey).run()
|
|
29
32
|
|
|
30
|
-
for (const
|
|
31
|
-
logger.verbose(`encrypting ${
|
|
32
|
-
if (
|
|
33
|
-
if (
|
|
34
|
-
logger.warn(
|
|
35
|
-
logger.help(`? add one with [echo "HELLO=World" > ${
|
|
33
|
+
for (const processedEnv of processedEnvs) {
|
|
34
|
+
logger.verbose(`encrypting ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
35
|
+
if (processedEnv.error) {
|
|
36
|
+
if (processedEnv.error.code === 'MISSING_ENV_FILE') {
|
|
37
|
+
logger.warn(processedEnv.error.message)
|
|
38
|
+
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx encrypt]`)
|
|
36
39
|
} else {
|
|
37
|
-
logger.warn(
|
|
40
|
+
logger.warn(processedEnv.error.message)
|
|
41
|
+
if (processedEnv.error.help) {
|
|
42
|
+
logger.help(processedEnv.error.help)
|
|
43
|
+
}
|
|
38
44
|
}
|
|
39
|
-
} else if (
|
|
40
|
-
fsx.writeFileX(
|
|
45
|
+
} else if (processedEnv.changed) {
|
|
46
|
+
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
41
47
|
|
|
42
|
-
logger.verbose(`encrypted ${
|
|
48
|
+
logger.verbose(`encrypted ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
43
49
|
} else {
|
|
44
|
-
logger.verbose(`no changes ${
|
|
50
|
+
logger.verbose(`no changes ${processedEnv.envFilepath} (${processedEnv.filepath})`)
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|
|
@@ -53,28 +59,19 @@ function encrypt () {
|
|
|
53
59
|
// do nothing - scenario when no .env files found
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
for (const
|
|
57
|
-
if (
|
|
58
|
-
logger.success(`✔ key added to .env.keys (${
|
|
62
|
+
for (const processedEnv of processedEnvs) {
|
|
63
|
+
if (processedEnv.privateKeyAdded) {
|
|
64
|
+
logger.success(`✔ key added to .env.keys (${processedEnv.privateKeyName})`)
|
|
59
65
|
|
|
60
66
|
if (!isIgnoringDotenvKeys()) {
|
|
61
67
|
logger.help2('ℹ add .env.keys to .gitignore: [echo ".env.keys" >> .gitignore]')
|
|
62
68
|
}
|
|
63
69
|
|
|
64
|
-
logger.help2(`ℹ run [${
|
|
70
|
+
logger.help2(`ℹ run [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx run -- yourcommand] to test decryption locally`)
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
} catch (error) {
|
|
68
|
-
|
|
69
|
-
if (error.help) {
|
|
70
|
-
logger.help(error.help)
|
|
71
|
-
}
|
|
72
|
-
if (error.debug) {
|
|
73
|
-
logger.debug(error.debug)
|
|
74
|
-
}
|
|
75
|
-
if (error.code) {
|
|
76
|
-
logger.debug(`ERROR_CODE: ${error.code}`)
|
|
77
|
-
}
|
|
74
|
+
catchAndLog(error)
|
|
78
75
|
process.exit(1)
|
|
79
76
|
}
|
|
80
77
|
}
|
package/src/cli/actions/set.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const fsx = require('./../../lib/helpers/fsx')
|
|
2
2
|
const { logger } = require('./../../shared/logger')
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const Sets = require('./../../lib/services/sets')
|
|
5
5
|
|
|
6
|
+
const catchAndLog = require('../../lib/helpers/catchAndLog')
|
|
6
7
|
const isIgnoringDotenvKeys = require('../../lib/helpers/isIgnoringDotenvKeys')
|
|
7
8
|
|
|
8
9
|
function set (key, value) {
|
|
@@ -19,11 +20,13 @@ function set (key, value) {
|
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
try {
|
|
23
|
+
const envs = this.envs
|
|
24
|
+
|
|
22
25
|
const {
|
|
23
|
-
|
|
26
|
+
processedEnvs,
|
|
24
27
|
changedFilepaths,
|
|
25
28
|
unchangedFilepaths
|
|
26
|
-
} =
|
|
29
|
+
} = new Sets(key, value, envs, encrypt).run()
|
|
27
30
|
|
|
28
31
|
let withEncryption = ''
|
|
29
32
|
|
|
@@ -31,21 +34,24 @@ function set (key, value) {
|
|
|
31
34
|
withEncryption = ' with encryption'
|
|
32
35
|
}
|
|
33
36
|
|
|
34
|
-
for (const
|
|
35
|
-
logger.verbose(`setting for ${
|
|
37
|
+
for (const processedEnv of processedEnvs) {
|
|
38
|
+
logger.verbose(`setting for ${processedEnv.envFilepath}`)
|
|
36
39
|
|
|
37
|
-
if (
|
|
38
|
-
if (
|
|
39
|
-
logger.warn(
|
|
40
|
-
logger.help(`? add one with [echo "HELLO=World" > ${
|
|
40
|
+
if (processedEnv.error) {
|
|
41
|
+
if (processedEnv.error.code === 'MISSING_ENV_FILE') {
|
|
42
|
+
logger.warn(processedEnv.error.message)
|
|
43
|
+
logger.help(`? add one with [echo "HELLO=World" > ${processedEnv.envFilepath}] and re-run [dotenvx set]`)
|
|
41
44
|
} else {
|
|
42
|
-
logger.warn(
|
|
45
|
+
logger.warn(processedEnv.error.message)
|
|
46
|
+
if (processedEnv.error.help) {
|
|
47
|
+
logger.help(processedEnv.error.help)
|
|
48
|
+
}
|
|
43
49
|
}
|
|
44
50
|
} else {
|
|
45
|
-
fsx.writeFileX(
|
|
51
|
+
fsx.writeFileX(processedEnv.filepath, processedEnv.envSrc)
|
|
46
52
|
|
|
47
|
-
logger.verbose(`${
|
|
48
|
-
logger.debug(`${
|
|
53
|
+
logger.verbose(`${processedEnv.key} set${withEncryption} (${processedEnv.envFilepath})`)
|
|
54
|
+
logger.debug(`${processedEnv.key} set${withEncryption} to ${processedEnv.value} (${processedEnv.envFilepath})`)
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
|
|
@@ -57,28 +63,19 @@ function set (key, value) {
|
|
|
57
63
|
// do nothing
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
for (const
|
|
61
|
-
if (
|
|
62
|
-
logger.success(`✔ key added to .env.keys (${
|
|
66
|
+
for (const processedEnv of processedEnvs) {
|
|
67
|
+
if (processedEnv.privateKeyAdded) {
|
|
68
|
+
logger.success(`✔ key added to .env.keys (${processedEnv.privateKeyName})`)
|
|
63
69
|
|
|
64
70
|
if (!isIgnoringDotenvKeys()) {
|
|
65
71
|
logger.help2('ℹ add .env.keys to .gitignore: [echo ".env.keys" >> .gitignore]')
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
logger.help2(`ℹ run [${
|
|
74
|
+
logger.help2(`ℹ run [${processedEnv.privateKeyName}='${processedEnv.privateKey}' dotenvx get ${key}] to test decryption locally`)
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
} catch (error) {
|
|
72
|
-
|
|
73
|
-
if (error.help) {
|
|
74
|
-
logger.help(error.help)
|
|
75
|
-
}
|
|
76
|
-
if (error.debug) {
|
|
77
|
-
logger.debug(error.debug)
|
|
78
|
-
}
|
|
79
|
-
if (error.code) {
|
|
80
|
-
logger.debug(`ERROR_CODE: ${error.code}`)
|
|
81
|
-
}
|
|
78
|
+
catchAndLog(error)
|
|
82
79
|
process.exit(1)
|
|
83
80
|
}
|
|
84
81
|
}
|
package/src/cli/dotenvx.js
CHANGED
|
@@ -59,7 +59,6 @@ program.command('run')
|
|
|
59
59
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\'])')
|
|
60
60
|
.action(function (...args) {
|
|
61
61
|
this.envs = envs
|
|
62
|
-
|
|
63
62
|
runAction.apply(this, args)
|
|
64
63
|
})
|
|
65
64
|
|
|
@@ -78,7 +77,6 @@ program.command('get')
|
|
|
78
77
|
.option('--format <type>', 'format of the output (json, shell, eval)', 'json')
|
|
79
78
|
.action(function (...args) {
|
|
80
79
|
this.envs = envs
|
|
81
|
-
|
|
82
80
|
getAction.apply(this, args)
|
|
83
81
|
})
|
|
84
82
|
|
|
@@ -90,30 +88,39 @@ program.command('set')
|
|
|
90
88
|
.allowUnknownOption()
|
|
91
89
|
.argument('KEY', 'KEY')
|
|
92
90
|
.argument('value', 'value')
|
|
93
|
-
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', '
|
|
91
|
+
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
94
92
|
.option('-c, --encrypt', 'encrypt value (default: true)', true)
|
|
95
93
|
.option('-p, --plain', 'store value as plain text', false)
|
|
96
|
-
.action(
|
|
94
|
+
.action(function (...args) {
|
|
95
|
+
this.envs = envs
|
|
96
|
+
setAction.apply(this, args)
|
|
97
|
+
})
|
|
97
98
|
|
|
98
99
|
// dotenvx encrypt
|
|
99
100
|
const encryptAction = require('./actions/encrypt')
|
|
100
101
|
program.command('encrypt')
|
|
101
102
|
.description('convert .env file(s) to encrypted .env file(s)')
|
|
102
|
-
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
103
|
+
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
103
104
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
104
105
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
105
106
|
.option('--stdout', 'send to stdout')
|
|
106
|
-
.action(
|
|
107
|
+
.action(function (...args) {
|
|
108
|
+
this.envs = envs
|
|
109
|
+
encryptAction.apply(this, args)
|
|
110
|
+
})
|
|
107
111
|
|
|
108
112
|
// dotenvx decrypt
|
|
109
113
|
const decryptAction = require('./actions/decrypt')
|
|
110
114
|
program.command('decrypt')
|
|
111
115
|
.description('convert encrypted .env file(s) to plain .env file(s)')
|
|
112
|
-
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
116
|
+
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)', collectEnvs('envFile'), [])
|
|
113
117
|
.option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
|
|
114
118
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
|
|
115
119
|
.option('--stdout', 'send to stdout')
|
|
116
|
-
.action(
|
|
120
|
+
.action(function (...args) {
|
|
121
|
+
this.envs = envs
|
|
122
|
+
decryptAction.apply(this, args)
|
|
123
|
+
})
|
|
117
124
|
|
|
118
125
|
// dotenvx keypair
|
|
119
126
|
const keypairAction = require('./actions/keypair')
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const { logger } = require('./../../shared/logger')
|
|
2
|
+
|
|
3
|
+
function catchAndLog (error) {
|
|
4
|
+
logger.error(error.message)
|
|
5
|
+
if (error.help) {
|
|
6
|
+
logger.help(error.help)
|
|
7
|
+
}
|
|
8
|
+
if (error.debug) {
|
|
9
|
+
logger.debug(error.debug)
|
|
10
|
+
}
|
|
11
|
+
if (error.code) {
|
|
12
|
+
logger.debug(`ERROR_CODE: ${error.code}`)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = catchAndLog
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const { decrypt } = require('eciesjs')
|
|
2
2
|
|
|
3
|
+
const truncate = require('./truncate')
|
|
4
|
+
|
|
3
5
|
const PREFIX = 'encrypted:'
|
|
4
6
|
|
|
5
7
|
function decryptValue (value, privateKey) {
|
|
@@ -27,9 +29,9 @@ function decryptValue (value, privateKey) {
|
|
|
27
29
|
break
|
|
28
30
|
} catch (e) {
|
|
29
31
|
if (e.message === 'Invalid private key') {
|
|
30
|
-
decryptionError = new Error(
|
|
32
|
+
decryptionError = new Error(`private key [${truncate(privateKey)}] looks invalid`)
|
|
31
33
|
} else if (e.message === 'Unsupported state or unable to authenticate data') {
|
|
32
|
-
decryptionError = new Error(
|
|
34
|
+
decryptionError = new Error(`private key [${truncate(privateKey)}] looks wrong`)
|
|
33
35
|
} else if (e.message === 'Point of length 65 was invalid. Expected 33 compressed bytes or 65 uncompressed bytes') {
|
|
34
36
|
decryptionError = new Error('encrypted data looks malformed')
|
|
35
37
|
} else {
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const dotenvPrivateKeyNames = require('./dotenvPrivateKeyNames')
|
|
2
|
+
const guessPrivateKeyFilename = require('./guessPrivateKeyFilename')
|
|
3
|
+
|
|
4
|
+
const TYPE_ENV_FILE = 'envFile'
|
|
5
|
+
const TYPE_ENV_VAULT_FILE = 'envVaultFile'
|
|
6
|
+
const DEFAULT_ENVS = [{ type: TYPE_ENV_FILE, value: '.env' }]
|
|
7
|
+
const DEFAULT_ENV_VAULTS = [{ type: TYPE_ENV_VAULT_FILE, value: '.env.vault' }]
|
|
8
|
+
|
|
9
|
+
function determineEnvsFromDotenvPrivateKey (privateKeyNames) {
|
|
10
|
+
const envs = []
|
|
11
|
+
|
|
12
|
+
for (const privateKeyName of privateKeyNames) {
|
|
13
|
+
const filename = guessPrivateKeyFilename(privateKeyName)
|
|
14
|
+
envs.push({ type: TYPE_ENV_FILE, value: filename })
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return envs
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function determineEnvs (envs = [], processEnv, DOTENV_KEY = '') {
|
|
21
|
+
const privateKeyNames = dotenvPrivateKeyNames(processEnv)
|
|
22
|
+
if (!envs || envs.length <= 0) {
|
|
23
|
+
// if process.env.DOTENV_PRIVATE_KEY or process.env.DOTENV_PRIVATE_KEY_${environment} is set, assume inline encryption methodology
|
|
24
|
+
if (privateKeyNames.length > 0) {
|
|
25
|
+
return determineEnvsFromDotenvPrivateKey(privateKeyNames)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (DOTENV_KEY.length > 0) {
|
|
29
|
+
// if DOTENV_KEY is set then default to look for .env.vault file
|
|
30
|
+
return DEFAULT_ENV_VAULTS
|
|
31
|
+
} else {
|
|
32
|
+
return DEFAULT_ENVS // default to .env file expectation
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
let fileAlreadySpecified = false // can be .env or .env.vault type
|
|
36
|
+
|
|
37
|
+
for (const env of envs) {
|
|
38
|
+
// if DOTENV_KEY set then we are checking if a .env.vault file is already specified
|
|
39
|
+
if (DOTENV_KEY.length > 0 && env.type === TYPE_ENV_VAULT_FILE) {
|
|
40
|
+
fileAlreadySpecified = true
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// if DOTENV_KEY not set then we are checking if a .env file is already specified
|
|
44
|
+
if (DOTENV_KEY.length <= 0 && env.type === TYPE_ENV_FILE) {
|
|
45
|
+
fileAlreadySpecified = true
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// return early since envs array objects already contain 1 .env.vault or .env file
|
|
50
|
+
if (fileAlreadySpecified) {
|
|
51
|
+
return envs
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// no .env.vault or .env file specified as a flag so we assume either .env.vault (if dotenv key is set) or a .env file
|
|
55
|
+
if (DOTENV_KEY.length > 0) {
|
|
56
|
+
// if DOTENV_KEY is set then default to look for .env.vault file
|
|
57
|
+
return [...DEFAULT_ENV_VAULTS, ...envs]
|
|
58
|
+
} else {
|
|
59
|
+
// if no DOTENV_KEY then default to look for .env file
|
|
60
|
+
return [...DEFAULT_ENVS, ...envs]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = determineEnvs
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const childProcess = require('child_process')
|
|
3
|
+
|
|
4
|
+
// helpers
|
|
5
|
+
const guessPrivateKeyName = require('./guessPrivateKeyName')
|
|
6
|
+
|
|
7
|
+
// services
|
|
8
|
+
const Keypair = require('./../services/keypair')
|
|
9
|
+
|
|
10
|
+
function findPrivateKey (envFilepath) {
|
|
11
|
+
const privateKeyName = guessPrivateKeyName(envFilepath)
|
|
12
|
+
|
|
13
|
+
let privateKey
|
|
14
|
+
try {
|
|
15
|
+
// if installed as sibling module
|
|
16
|
+
const projectRoot = path.resolve(process.cwd())
|
|
17
|
+
const dotenvxProPath = require.resolve('@dotenvx/dotenvx-pro', { paths: [projectRoot] })
|
|
18
|
+
const { keypair } = require(dotenvxProPath)
|
|
19
|
+
privateKey = keypair(envFilepath, privateKeyName)
|
|
20
|
+
} catch (_e) {
|
|
21
|
+
try {
|
|
22
|
+
// if installed as binary cli
|
|
23
|
+
privateKey = childProcess.execSync(`dotenvx-pro keypair ${privateKeyName} -f ${envFilepath}`, { stdio: ['pipe', 'pipe', 'ignore'] }).toString().trim()
|
|
24
|
+
} catch (_e) {
|
|
25
|
+
// fallback to local KeyPair - smart enough to handle process.env, .env.keys, etc
|
|
26
|
+
privateKey = new Keypair(envFilepath, privateKeyName).run()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return privateKey
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = findPrivateKey
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const childProcess = require('child_process')
|
|
3
|
+
|
|
4
|
+
// helpers
|
|
5
|
+
const guessPublicKeyName = require('./guessPublicKeyName')
|
|
6
|
+
|
|
7
|
+
// services
|
|
8
|
+
const Keypair = require('./../services/keypair')
|
|
9
|
+
|
|
10
|
+
function findPublicKey (envFilepath) {
|
|
11
|
+
const publicKeyName = guessPublicKeyName(envFilepath)
|
|
12
|
+
|
|
13
|
+
let publicKey
|
|
14
|
+
try {
|
|
15
|
+
// if installed as sibling module
|
|
16
|
+
const projectRoot = path.resolve(process.cwd())
|
|
17
|
+
const dotenvxProPath = require.resolve('@dotenvx/dotenvx-pro', { paths: [projectRoot] })
|
|
18
|
+
const { keypair } = require(dotenvxProPath)
|
|
19
|
+
publicKey = keypair(envFilepath, publicKeyName)
|
|
20
|
+
} catch (_e) {
|
|
21
|
+
try {
|
|
22
|
+
// if installed as binary cli
|
|
23
|
+
publicKey = childProcess.execSync(`dotenvx-pro keypair ${publicKeyName} -f ${envFilepath}`, { stdio: ['pipe', 'pipe', 'ignore'] }).toString().trim()
|
|
24
|
+
} catch (_e) {
|
|
25
|
+
// fallback to local KeyPair - smart enough to handle process.env, .env.keys, etc
|
|
26
|
+
publicKey = new Keypair(envFilepath, publicKeyName).run()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return publicKey
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = findPublicKey
|
|
@@ -7,7 +7,7 @@ function isFullyEncrypted (src) {
|
|
|
7
7
|
const parsed = dotenv.parse(src)
|
|
8
8
|
|
|
9
9
|
for (const [key, value] of Object.entries(parsed)) {
|
|
10
|
-
const result = isEncrypted(
|
|
10
|
+
const result = isEncrypted(value) || isPublicKey(key, value)
|
|
11
11
|
if (!result) {
|
|
12
12
|
return false
|
|
13
13
|
}
|
package/src/lib/main.js
CHANGED
|
@@ -10,10 +10,7 @@ const { getColor, bold } = require('./../shared/colors')
|
|
|
10
10
|
const Ls = require('./services/ls')
|
|
11
11
|
const Get = require('./services/get')
|
|
12
12
|
const Run = require('./services/run')
|
|
13
|
-
const Sets = require('./services/sets')
|
|
14
13
|
const Keypair = require('./services/keypair')
|
|
15
|
-
const Encrypt = require('./services/encrypt')
|
|
16
|
-
const Decrypt = require('./services/decrypt')
|
|
17
14
|
const Genexample = require('./services/genexample')
|
|
18
15
|
|
|
19
16
|
// helpers
|
|
@@ -196,21 +193,6 @@ const get = function (
|
|
|
196
193
|
return new Get(key, envs, overload, DOTENV_KEY, all).run()
|
|
197
194
|
}
|
|
198
195
|
|
|
199
|
-
/** @type {import('./main').set} */
|
|
200
|
-
const set = function (key, value, envFile, encrypt) {
|
|
201
|
-
return new Sets(key, value, envFile, encrypt).run()
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/** @type {import('./main').encrypt} */
|
|
205
|
-
const encrypt = function (envFile, key, excludeKey) {
|
|
206
|
-
return new Encrypt(envFile, key, excludeKey).run()
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/** @type {import('./main').encrypt} */
|
|
210
|
-
const decrypt = function (envFile, key, excludeKey) {
|
|
211
|
-
return new Decrypt(envFile, key, excludeKey).run()
|
|
212
|
-
}
|
|
213
|
-
|
|
214
196
|
/** @type {import('./main').keypair} */
|
|
215
197
|
const keypair = function (envFile, key) {
|
|
216
198
|
return new Keypair(envFile, key).run()
|
|
@@ -222,11 +204,8 @@ module.exports = {
|
|
|
222
204
|
configDotenv,
|
|
223
205
|
parse,
|
|
224
206
|
// actions related
|
|
225
|
-
encrypt,
|
|
226
|
-
decrypt,
|
|
227
207
|
ls,
|
|
228
208
|
get,
|
|
229
|
-
set,
|
|
230
209
|
keypair,
|
|
231
210
|
genexample,
|
|
232
211
|
// expose for libs depending on @dotenvx/dotenvx - like dotenvx-pro
|