@dotenvx/dotenvx 1.69.1 → 1.70.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 +13 -1
- package/README.md +21 -15
- package/package.json +7 -6
- package/src/cli/actions/decrypt.js +8 -6
- package/src/cli/actions/encrypt.js +16 -22
- package/src/cli/actions/get.js +4 -4
- package/src/cli/actions/keypair.js +4 -4
- package/src/cli/actions/normalizeArmorOptions.js +11 -0
- package/src/cli/actions/rotate.js +6 -12
- package/src/cli/actions/run.js +8 -8
- package/src/cli/actions/set.js +6 -10
- package/src/cli/commands/ext.js +1 -1
- package/src/cli/dotenvx.js +33 -35
- package/src/db/session.js +9 -9
- package/src/lib/extensions/{vlt.js → armor.js} +4 -4
- package/src/lib/helpers/cryptography/{vltKeypair.js → armorKeypair.js} +4 -4
- package/src/lib/helpers/cryptography/armorKeypairSync.js +14 -0
- package/src/lib/helpers/cryptography/index.js +2 -2
- package/src/lib/helpers/cryptography/mutateKeysSrc.js +2 -2
- package/src/lib/helpers/cryptography/mutateKeysSrcSync.js +2 -2
- package/src/lib/helpers/cryptography/provision.js +8 -8
- package/src/lib/helpers/cryptography/provisionSync.js +6 -6
- package/src/lib/helpers/cryptography/provisionWithPrivateKey.js +1 -1
- package/src/lib/helpers/executeDynamic.js +57 -19
- package/src/lib/helpers/keyResolution/keyValues.js +13 -6
- package/src/lib/helpers/keyResolution/keyValuesFromEnvSrc.js +12 -5
- package/src/lib/helpers/keyResolution/keyValuesSync.js +15 -8
- package/src/lib/main.d.ts +37 -13
- package/src/lib/main.js +12 -16
- package/src/lib/services/decrypt.js +5 -3
- package/src/lib/services/encrypt.js +4 -4
- package/src/lib/services/get.js +4 -4
- package/src/lib/services/keypair.js +4 -4
- package/src/lib/services/rotate.js +9 -9
- package/src/lib/services/run.js +21 -8
- package/src/lib/services/sets.js +6 -6
- package/src/cli/actions/normalizeVltOptions.js +0 -10
- package/src/lib/helpers/cryptography/vltKeypairSync.js +0 -14
package/src/cli/dotenvx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/* c8 ignore start */
|
|
4
|
-
const { Command } = require('commander')
|
|
4
|
+
const { Command, Option } = require('commander')
|
|
5
5
|
const program = new Command()
|
|
6
6
|
|
|
7
7
|
const { setLogLevel, logger } = require('../shared/logger')
|
|
@@ -43,7 +43,7 @@ program
|
|
|
43
43
|
setLogLevel(options)
|
|
44
44
|
})
|
|
45
45
|
|
|
46
|
-
// for dynamic loading of dotenvx-
|
|
46
|
+
// for dynamic loading of dotenvx-armor, etc
|
|
47
47
|
program
|
|
48
48
|
.argument('[command]', 'dynamic command')
|
|
49
49
|
.argument('[args...]', 'dynamic command arguments')
|
|
@@ -70,8 +70,9 @@ program.command('run')
|
|
|
70
70
|
.option('--strict', 'process.exit(1) on any errors', false)
|
|
71
71
|
.option('--convention <name>', 'load a .env convention (available conventions: [\'nextjs\', \'flow\'])')
|
|
72
72
|
.option('--ignore <errorCodes...>', 'error code(s) to ignore (example: --ignore=MISSING_ENV_FILE)')
|
|
73
|
-
.option('--no-
|
|
74
|
-
.
|
|
73
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
74
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
75
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
75
76
|
.action(function (...args) {
|
|
76
77
|
this.envs = envs
|
|
77
78
|
return require('./actions/run').apply(this, args)
|
|
@@ -93,8 +94,9 @@ program.command('get')
|
|
|
93
94
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
94
95
|
.option('--pp', 'pretty print output (alias)')
|
|
95
96
|
.option('--format <type>', 'format of the output (json, shell, colon, eval)', 'json')
|
|
96
|
-
.option('--no-
|
|
97
|
-
.
|
|
97
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
98
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
99
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
98
100
|
.action(function (...args) {
|
|
99
101
|
this.envs = envs
|
|
100
102
|
return require('./actions/get').apply(this, args)
|
|
@@ -113,8 +115,9 @@ program.command('set')
|
|
|
113
115
|
.option('-c, --encrypt', 'encrypt value', true)
|
|
114
116
|
.option('-p, --plain', 'store value as plain text', false)
|
|
115
117
|
.option('--no-create', 'do not create .env file(s) when missing')
|
|
116
|
-
.option('--no-
|
|
117
|
-
.
|
|
118
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
119
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
120
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
118
121
|
.action(function (...args) {
|
|
119
122
|
this.envs = envs
|
|
120
123
|
return require('./actions/set').apply(this, args)
|
|
@@ -128,10 +131,11 @@ program.command('encrypt')
|
|
|
128
131
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
129
132
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
130
133
|
.option('--stdout', 'send to stdout')
|
|
131
|
-
.option('--token <token>', 'set
|
|
134
|
+
.option('--token <token>', 'set Armor ⛨ token')
|
|
132
135
|
.option('--no-create', 'do not create .env file(s) when missing')
|
|
133
|
-
.option('--no-
|
|
134
|
-
.
|
|
136
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
137
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
138
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
135
139
|
.action(function (...args) {
|
|
136
140
|
this.envs = envs
|
|
137
141
|
return require('./actions/encrypt').apply(this, args)
|
|
@@ -144,8 +148,9 @@ program.command('decrypt')
|
|
|
144
148
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
145
149
|
.option('-k, --key <keys...>', 'keys(s) to decrypt (default: all keys in file)')
|
|
146
150
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from decryption (default: none)')
|
|
147
|
-
.option('--no-
|
|
148
|
-
.
|
|
151
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
152
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
153
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
149
154
|
.option('--stdout', 'send to stdout')
|
|
150
155
|
.action(function (...args) {
|
|
151
156
|
this.envs = envs
|
|
@@ -159,8 +164,9 @@ program.command('rotate')
|
|
|
159
164
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
160
165
|
.option('-k, --key <keys...>', 'keys(s) to encrypt (default: all keys in file)')
|
|
161
166
|
.option('-ek, --exclude-key <excludeKeys...>', 'keys(s) to exclude from encryption (default: none)')
|
|
162
|
-
.option('--no-
|
|
163
|
-
.
|
|
167
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
168
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
169
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
164
170
|
.option('--stdout', 'send to stdout')
|
|
165
171
|
.action(function (...args) {
|
|
166
172
|
this.envs = envs
|
|
@@ -174,8 +180,9 @@ program.command('keypair')
|
|
|
174
180
|
.argument('[KEY]', 'environment variable key name')
|
|
175
181
|
.option('-f, --env-file <paths...>', 'path(s) to your env file(s)')
|
|
176
182
|
.option('-fk, --env-keys-file <path>', 'path to your .env.keys file (default: same path as your env file)')
|
|
177
|
-
.option('--no-
|
|
178
|
-
.
|
|
183
|
+
.option('--no-armor', 'disable dotenvx-armor features')
|
|
184
|
+
.addOption(new Option('--no-vlt', 'disable dotenvx-vlt features (deprecated. use --no-armor)').hideHelp())
|
|
185
|
+
.addOption(new Option('--no-ops', 'disable dotenvx-ops features (deprecated. use --no-armor)').hideHelp())
|
|
179
186
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
180
187
|
.option('--pp', 'pretty print output (alias)')
|
|
181
188
|
.option('--format <type>', 'format of the output (json, shell, colon)', 'json')
|
|
@@ -202,12 +209,12 @@ program.command('doctor', { hidden: true })
|
|
|
202
209
|
})
|
|
203
210
|
|
|
204
211
|
// dotenvx login
|
|
205
|
-
program.command('login')
|
|
206
|
-
.description('
|
|
212
|
+
program.command('login', { hidden: true })
|
|
213
|
+
.description('')
|
|
207
214
|
.allowUnknownOption()
|
|
208
215
|
.action(() => {
|
|
209
|
-
const rawArgs = ['
|
|
210
|
-
executeDynamic(program, '
|
|
216
|
+
const rawArgs = ['armor', 'login', ...process.argv.slice(3)]
|
|
217
|
+
executeDynamic(program, 'armor', rawArgs)
|
|
211
218
|
})
|
|
212
219
|
|
|
213
220
|
// dotenvx logout
|
|
@@ -215,17 +222,8 @@ program.command('logout', { hidden: true })
|
|
|
215
222
|
.description('log out of your dotenvx account')
|
|
216
223
|
.allowUnknownOption()
|
|
217
224
|
.action(() => {
|
|
218
|
-
const rawArgs = ['
|
|
219
|
-
executeDynamic(program, '
|
|
220
|
-
})
|
|
221
|
-
|
|
222
|
-
// dotenvx armor
|
|
223
|
-
program.command('armor', { hidden: true })
|
|
224
|
-
.description('ARMORED KEYS ⛨')
|
|
225
|
-
.allowUnknownOption()
|
|
226
|
-
.action((args) => {
|
|
227
|
-
const rawArgs = ['ops', 'armor', ...process.argv.slice(3)]
|
|
228
|
-
executeDynamic(program, 'ops', rawArgs)
|
|
225
|
+
const rawArgs = ['armor', 'logout', ...process.argv.slice(3)]
|
|
226
|
+
executeDynamic(program, 'armor', rawArgs)
|
|
229
227
|
})
|
|
230
228
|
|
|
231
229
|
// dotenvx help
|
|
@@ -244,11 +242,11 @@ program.command('help [command]')
|
|
|
244
242
|
}
|
|
245
243
|
})
|
|
246
244
|
|
|
247
|
-
// dotenvx
|
|
245
|
+
// dotenvx armor
|
|
248
246
|
program.addHelpText('after', ' ')
|
|
249
247
|
program.addHelpText('after', 'Advanced: ')
|
|
250
|
-
program.addHelpText('after', '
|
|
251
|
-
program.addHelpText('after', ' ext
|
|
248
|
+
program.addHelpText('after', ' armor ⛨ ARMORED KEYS [www.dotenvx.com/armor]')
|
|
249
|
+
program.addHelpText('after', ' ext ⊕ extensions')
|
|
252
250
|
|
|
253
251
|
// dotenvx ext
|
|
254
252
|
program.addCommand(require('./commands/ext'))
|
package/src/db/session.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Armor = require('./../lib/extensions/armor')
|
|
2
2
|
const { logger } = require('./../shared/logger')
|
|
3
3
|
|
|
4
4
|
class Session {
|
|
5
5
|
constructor () {
|
|
6
|
-
this.
|
|
6
|
+
this.armor = new Armor()
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
//
|
|
10
|
-
//
|
|
10
|
+
// armor status helpers
|
|
11
11
|
//
|
|
12
|
-
async
|
|
13
|
-
const status = await this.
|
|
14
|
-
logger.debug(`
|
|
12
|
+
async noArmor () {
|
|
13
|
+
const status = await this.armor.status()
|
|
14
|
+
logger.debug(`armor: ${status}`)
|
|
15
15
|
return status === 'off'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
const status = this.
|
|
20
|
-
logger.debug(`
|
|
18
|
+
noArmorSync () {
|
|
19
|
+
const status = this.armor.statusSync()
|
|
20
|
+
logger.debug(`armor: ${status}`)
|
|
21
21
|
return status === 'off'
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -4,9 +4,9 @@ const util = require('util')
|
|
|
4
4
|
const { logger } = require('../../shared/logger')
|
|
5
5
|
|
|
6
6
|
const execFile = util.promisify(childProcess.execFile)
|
|
7
|
-
const BINARY_NAMES = ['dotenvx-vlt', 'dotenvx-ops']
|
|
7
|
+
const BINARY_NAMES = ['dotenvx-armor', 'dotenvx-vlt', 'dotenvx-ops']
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class Armor {
|
|
10
10
|
async status () {
|
|
11
11
|
if (this._isForcedOff()) return 'off'
|
|
12
12
|
|
|
@@ -195,8 +195,8 @@ class Vlt {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
_isForcedOff () {
|
|
198
|
-
return process.env.
|
|
198
|
+
return process.env.DOTENVX_NO_ARMOR === 'true' || process.env.DOTENVX_NO_VLT === 'true' || process.env.DOTENVX_NO_OPS === 'true'
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
module.exports =
|
|
202
|
+
module.exports = Armor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const
|
|
1
|
+
const Armor = require('../../extensions/armor')
|
|
2
2
|
|
|
3
|
-
async function
|
|
3
|
+
async function armorKeypair (existingPublicKey, options = {}) {
|
|
4
4
|
const hooks = options.hooks || {}
|
|
5
5
|
if (hooks.before) await hooks.before()
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ async function vltKeypair (existingPublicKey, options = {}) {
|
|
|
13
13
|
|
|
14
14
|
let kp
|
|
15
15
|
try {
|
|
16
|
-
kp = await new
|
|
16
|
+
kp = await new Armor().keypair(existingPublicKey, keypairOptions)
|
|
17
17
|
} finally {
|
|
18
18
|
if (hooks.after) await hooks.after()
|
|
19
19
|
}
|
|
@@ -27,4 +27,4 @@ async function vltKeypair (existingPublicKey, options = {}) {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
module.exports =
|
|
30
|
+
module.exports = armorKeypair
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const Armor = require('../../extensions/armor')
|
|
2
|
+
|
|
3
|
+
function armorKeypairSync (existingPublicKey, options = {}) {
|
|
4
|
+
const kp = new Armor().keypairSync(existingPublicKey, options)
|
|
5
|
+
const publicKey = kp.public_key
|
|
6
|
+
const privateKey = kp.private_key
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
publicKey,
|
|
10
|
+
privateKey
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = armorKeypairSync
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
armorKeypair: require('./armorKeypair'),
|
|
3
|
+
armorKeypairSync: require('./armorKeypairSync'),
|
|
4
4
|
localKeypair: require('./localKeypair'),
|
|
5
5
|
encryptValue: require('./encryptValue'),
|
|
6
6
|
decryptKeyValue: require('./decryptKeyValue'),
|
|
@@ -2,7 +2,7 @@ const FIRST_TIME_KEYS_SRC = [
|
|
|
2
2
|
'#/------------------!DOTENV_PRIVATE_KEYS!-------------------/',
|
|
3
3
|
'#/ private decryption keys. DO NOT commit to source control /',
|
|
4
4
|
'#/ [how it works](https://dotenvx.com/encryption) /',
|
|
5
|
-
'#/
|
|
5
|
+
'#/ ⛨ ARMORED KEYS: `dotenvx armor up` /',
|
|
6
6
|
'#/----------------------------------------------------------/'
|
|
7
7
|
].join('\n')
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ async function mutateKeysSrc ({ envFilepath, keysFilepath, privateKeyName, priva
|
|
|
25
25
|
keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
|
|
26
26
|
keysSrc = `${keysSrc}\n${appendPrivateKey}`
|
|
27
27
|
|
|
28
|
-
await fsx.writeFileX(resolvedKeysFilepath, keysSrc) // TODO: don't write if
|
|
28
|
+
await fsx.writeFileX(resolvedKeysFilepath, keysSrc) // TODO: don't write if armor
|
|
29
29
|
|
|
30
30
|
const envKeysFilepath = keysFilepath || path.join(path.dirname(envFilepath), path.basename(resolvedKeysFilepath))
|
|
31
31
|
|
|
@@ -2,7 +2,7 @@ const FIRST_TIME_KEYS_SRC = [
|
|
|
2
2
|
'#/------------------!DOTENV_PRIVATE_KEYS!-------------------/',
|
|
3
3
|
'#/ private decryption keys. DO NOT commit to source control /',
|
|
4
4
|
'#/ [how it works](https://dotenvx.com/encryption) /',
|
|
5
|
-
'#/
|
|
5
|
+
'#/ ⛨ ARMORED KEYS: `dotenvx armor up` /',
|
|
6
6
|
'#/----------------------------------------------------------/'
|
|
7
7
|
].join('\n')
|
|
8
8
|
|
|
@@ -25,7 +25,7 @@ function mutateKeysSrcSync ({ envFilepath, keysFilepath, privateKeyName, private
|
|
|
25
25
|
keysSrc = keysSrc.length > 1 ? keysSrc : `${FIRST_TIME_KEYS_SRC}\n`
|
|
26
26
|
keysSrc = `${keysSrc}\n${appendPrivateKey}`
|
|
27
27
|
|
|
28
|
-
fsx.writeFileXSync(resolvedKeysFilepath, keysSrc) // TODO: don't write if
|
|
28
|
+
fsx.writeFileXSync(resolvedKeysFilepath, keysSrc) // TODO: don't write if armor
|
|
29
29
|
|
|
30
30
|
const envKeysFilepath = keysFilepath || path.join(path.dirname(envFilepath), path.basename(resolvedKeysFilepath))
|
|
31
31
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const mutateSrc = require('./mutateSrc')
|
|
2
2
|
const mutateKeysSrc = require('./mutateKeysSrc')
|
|
3
|
-
const
|
|
3
|
+
const armorKeypair = require('./armorKeypair')
|
|
4
4
|
const localKeypair = require('./localKeypair')
|
|
5
5
|
const { keyNames } = require('../keyResolution')
|
|
6
6
|
|
|
7
|
-
async function provision ({ envSrc, envFilepath, keysFilepath,
|
|
8
|
-
|
|
9
|
-
if (!
|
|
10
|
-
|
|
7
|
+
async function provision ({ envSrc, envFilepath, keysFilepath, noArmor, token, keypairHooks, selectKeyStorage }) {
|
|
8
|
+
noArmor = noArmor !== false
|
|
9
|
+
if (!noArmor && selectKeyStorage) {
|
|
10
|
+
noArmor = await selectKeyStorage() !== 'armored'
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
const { publicKeyName, privateKeyName } = keyNames(envFilepath)
|
|
@@ -19,12 +19,12 @@ async function provision ({ envSrc, envFilepath, keysFilepath, noVlt, token, key
|
|
|
19
19
|
let localPrivateKeyAdded = false
|
|
20
20
|
let remotePrivateKeyAdded = false
|
|
21
21
|
|
|
22
|
-
if (
|
|
22
|
+
if (noArmor) {
|
|
23
23
|
const kp = localKeypair()
|
|
24
24
|
publicKey = kp.publicKey
|
|
25
25
|
privateKey = kp.privateKey
|
|
26
26
|
} else {
|
|
27
|
-
const kp = await
|
|
27
|
+
const kp = await armorKeypair(undefined, { token, envFilepath, hooks: keypairHooks })
|
|
28
28
|
publicKey = kp.publicKey
|
|
29
29
|
privateKey = kp.privateKey
|
|
30
30
|
}
|
|
@@ -32,7 +32,7 @@ async function provision ({ envSrc, envFilepath, keysFilepath, noVlt, token, key
|
|
|
32
32
|
const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
|
|
33
33
|
envSrc = mutated.envSrc
|
|
34
34
|
|
|
35
|
-
if (
|
|
35
|
+
if (noArmor) {
|
|
36
36
|
const mutated = await mutateKeysSrc({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
|
|
37
37
|
keysSrc = mutated.keysSrc
|
|
38
38
|
envKeysFilepath = mutated.envKeysFilepath
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const mutateSrc = require('./mutateSrc')
|
|
2
2
|
const mutateKeysSrcSync = require('./mutateKeysSrcSync')
|
|
3
|
-
const
|
|
3
|
+
const armorKeypairSync = require('./armorKeypairSync')
|
|
4
4
|
const localKeypair = require('./localKeypair')
|
|
5
5
|
const { keyNames } = require('../keyResolution')
|
|
6
6
|
|
|
7
|
-
function provisionSync ({ envSrc, envFilepath, keysFilepath,
|
|
8
|
-
|
|
7
|
+
function provisionSync ({ envSrc, envFilepath, keysFilepath, noArmor }) {
|
|
8
|
+
noArmor = noArmor !== false
|
|
9
9
|
const { publicKeyName, privateKeyName } = keyNames(envFilepath)
|
|
10
10
|
|
|
11
11
|
let publicKey
|
|
@@ -15,12 +15,12 @@ function provisionSync ({ envSrc, envFilepath, keysFilepath, noVlt }) {
|
|
|
15
15
|
let localPrivateKeyAdded = false
|
|
16
16
|
let remotePrivateKeyAdded = false
|
|
17
17
|
|
|
18
|
-
if (
|
|
18
|
+
if (noArmor) {
|
|
19
19
|
const kp = localKeypair()
|
|
20
20
|
publicKey = kp.publicKey
|
|
21
21
|
privateKey = kp.privateKey
|
|
22
22
|
} else {
|
|
23
|
-
const kp =
|
|
23
|
+
const kp = armorKeypairSync(undefined, { envFilepath })
|
|
24
24
|
publicKey = kp.publicKey
|
|
25
25
|
privateKey = kp.privateKey
|
|
26
26
|
}
|
|
@@ -28,7 +28,7 @@ function provisionSync ({ envSrc, envFilepath, keysFilepath, noVlt }) {
|
|
|
28
28
|
const mutated = mutateSrc({ envSrc, envFilepath, keysFilepath, publicKeyName, publicKeyValue: publicKey })
|
|
29
29
|
envSrc = mutated.envSrc
|
|
30
30
|
|
|
31
|
-
if (
|
|
31
|
+
if (noArmor) {
|
|
32
32
|
const mutated = mutateKeysSrcSync({ envFilepath, keysFilepath, privateKeyName, privateKeyValue: privateKey })
|
|
33
33
|
keysSrc = mutated.keysSrc
|
|
34
34
|
envKeysFilepath = mutated.envKeysFilepath
|
|
@@ -3,7 +3,7 @@ const mutateSrc = require('./mutateSrc')
|
|
|
3
3
|
const localKeypair = require('./localKeypair')
|
|
4
4
|
|
|
5
5
|
function provisionWithPrivateKey ({ envSrc, envFilepath, keysFilepath, privateKeyValue, publicKeyValue, publicKeyName }) {
|
|
6
|
-
const { publicKey, privateKey } = localKeypair(privateKeyValue) //
|
|
6
|
+
const { publicKey, privateKey } = localKeypair(privateKeyValue) // noArmor doesn't matter here since privateKeyValue was already discovered prior (via armor and local) and passed as privateKeyValue
|
|
7
7
|
|
|
8
8
|
// if derivation doesn't match what's in the file (or preset in env)
|
|
9
9
|
if (publicKeyValue && publicKeyValue !== publicKey) {
|
|
@@ -2,23 +2,35 @@ const path = require('path')
|
|
|
2
2
|
const childProcess = require('child_process')
|
|
3
3
|
const { logger } = require('../../shared/logger')
|
|
4
4
|
|
|
5
|
-
function
|
|
6
|
-
return 'curl -sfS https://dotenvx.sh/vlt | sh'
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function vltBanner (installCommand) {
|
|
5
|
+
function armorBanner () {
|
|
10
6
|
const lines = [
|
|
7
|
+
' [www.dotenvx.com/armor]',
|
|
8
|
+
'–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––',
|
|
9
|
+
' __ ____ __ ',
|
|
10
|
+
' | || |',
|
|
11
|
+
' | __||__ |',
|
|
12
|
+
' | ‾‾||‾‾ |',
|
|
13
|
+
' | || |',
|
|
14
|
+
' \\ || /',
|
|
15
|
+
' \\ __ /',
|
|
16
|
+
'',
|
|
17
|
+
' Dotenvx Armor ⛨',
|
|
18
|
+
'',
|
|
19
|
+
' ARMORED KEYS',
|
|
20
|
+
' Private keys. Off device. Under guard.',
|
|
11
21
|
'',
|
|
12
|
-
'
|
|
13
|
-
' ██║ ██║██║ ╚══██╔══╝',
|
|
14
|
-
' ██║ ██║██║ ██║ ',
|
|
15
|
-
' ╚██╗ ██╔╝██║ ██║ [www.dotenvx.com/vlt]',
|
|
16
|
-
' ╚████╔╝ ███████╗██║ ',
|
|
17
|
-
' ╚═══╝ ╚══════╝╚═╝ ',
|
|
22
|
+
' -',
|
|
18
23
|
'',
|
|
19
|
-
'
|
|
20
|
-
|
|
21
|
-
'
|
|
24
|
+
' Install one',
|
|
25
|
+
' [curl -sfS https://dotenvx.sh/armor | sh]',
|
|
26
|
+
' [npm i @dotenvx/dotenvx-armor --save]',
|
|
27
|
+
'',
|
|
28
|
+
' -',
|
|
29
|
+
'',
|
|
30
|
+
' Then',
|
|
31
|
+
' [dotenvx armor up]',
|
|
32
|
+
' (sign in when prompted)',
|
|
33
|
+
''
|
|
22
34
|
]
|
|
23
35
|
|
|
24
36
|
const innerWidth = Math.max(67, ...lines.map((line) => line.length))
|
|
@@ -29,6 +41,26 @@ function vltBanner (installCommand) {
|
|
|
29
41
|
return `${top}\n${middle}\n${bottom}`
|
|
30
42
|
}
|
|
31
43
|
|
|
44
|
+
function dynamicAttempts (command, forwardedArgs) {
|
|
45
|
+
if (command === 'vlt') {
|
|
46
|
+
return [
|
|
47
|
+
['dotenvx-armor', forwardedArgs],
|
|
48
|
+
['dotenvx-vlt', forwardedArgs],
|
|
49
|
+
['dotenvx-ops', forwardedArgs]
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (command === 'ops') {
|
|
54
|
+
return [
|
|
55
|
+
['dotenvx-armor', forwardedArgs],
|
|
56
|
+
['dotenvx-ops', forwardedArgs],
|
|
57
|
+
['dotenvx-vlt', forwardedArgs]
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return [[`dotenvx-${command}`, forwardedArgs]]
|
|
62
|
+
}
|
|
63
|
+
|
|
32
64
|
function executeDynamic (program, command, rawArgs) {
|
|
33
65
|
if (!command) {
|
|
34
66
|
program.outputHelp()
|
|
@@ -47,14 +79,20 @@ function executeDynamic (program, command, rawArgs) {
|
|
|
47
79
|
const newPath = `${binPath}:${process.env.PATH}`
|
|
48
80
|
const env = { ...process.env, PATH: newPath }
|
|
49
81
|
|
|
50
|
-
const
|
|
82
|
+
const spawnOptions = { stdio: 'inherit', env }
|
|
83
|
+
let result
|
|
84
|
+
for (const [spawnCommand, spawnArgs] of dynamicAttempts(command, forwardedArgs)) {
|
|
85
|
+
result = childProcess.spawnSync(spawnCommand, spawnArgs, spawnOptions)
|
|
86
|
+
if (!result.error) break
|
|
87
|
+
}
|
|
88
|
+
|
|
51
89
|
if (result.error) {
|
|
52
90
|
if (command === 'vlt') {
|
|
53
|
-
|
|
54
|
-
console.log(vltBanner(installCommand))
|
|
91
|
+
console.log(armorBanner())
|
|
55
92
|
} else if (command === 'ops') {
|
|
56
|
-
|
|
57
|
-
|
|
93
|
+
console.log(armorBanner())
|
|
94
|
+
} else if (command === 'armor') {
|
|
95
|
+
console.log(armorBanner())
|
|
58
96
|
} else {
|
|
59
97
|
logger.info(`error: unknown command '${command}'`)
|
|
60
98
|
}
|
|
@@ -5,7 +5,7 @@ const dotenvParse = require('./../dotenvParse')
|
|
|
5
5
|
const keyNames = require('./keyNames')
|
|
6
6
|
const readProcessKey = require('./readProcessKey')
|
|
7
7
|
const readFileKey = require('./readFileKey')
|
|
8
|
-
const
|
|
8
|
+
const armorKeypair = require('../cryptography/armorKeypair')
|
|
9
9
|
|
|
10
10
|
async function invertForPrivateKeyName (filepath) {
|
|
11
11
|
const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
|
|
@@ -34,13 +34,14 @@ async function invertForPrivateKeyName (filepath) {
|
|
|
34
34
|
|
|
35
35
|
async function keyValues (filepath, opts = {}) {
|
|
36
36
|
let keysFilepath = opts.keysFilepath || null
|
|
37
|
-
const
|
|
37
|
+
const noArmor = opts.noArmor === true
|
|
38
38
|
const names = keyNames(filepath)
|
|
39
39
|
const publicKeyName = names.publicKeyName // DOTENV_PUBLIC_KEY_${ENVIRONMENT}
|
|
40
40
|
let privateKeyName = names.privateKeyName // DOTENV_PRIVATE_KEY_${ENVIRONMENT}
|
|
41
41
|
|
|
42
42
|
let publicKey = null
|
|
43
43
|
let privateKey = null
|
|
44
|
+
let privateKeySource = null
|
|
44
45
|
|
|
45
46
|
// public key: process.env first, then .env*
|
|
46
47
|
publicKey = readProcessKey(publicKeyName)
|
|
@@ -70,16 +71,22 @@ async function keyValues (filepath, opts = {}) {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
//
|
|
74
|
-
if (!
|
|
75
|
-
const kp = await
|
|
74
|
+
// armor
|
|
75
|
+
if (!noArmor && !privateKey && publicKey && publicKey.length > 0) {
|
|
76
|
+
const kp = await armorKeypair(publicKey, { envFilepath: filepath, hooks: opts.keypairHooks })
|
|
76
77
|
privateKey = kp.privateKey
|
|
78
|
+
privateKeySource = 'armor'
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
|
|
81
|
+
const result = {
|
|
80
82
|
publicKeyValue: publicKey || null, // important to make sure name is rendered
|
|
81
83
|
privateKeyValue: privateKey || null // important to make sure name is rendered
|
|
82
84
|
}
|
|
85
|
+
if (privateKeySource) {
|
|
86
|
+
result.privateKeySource = privateKeySource
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
module.exports = keyValues
|
|
@@ -2,7 +2,7 @@ const path = require('path')
|
|
|
2
2
|
|
|
3
3
|
const dotenvParse = require('./../dotenvParse')
|
|
4
4
|
const readFileKeySync = require('./readFileKeySync')
|
|
5
|
-
const
|
|
5
|
+
const armorKeypairSync = require('../cryptography/armorKeypairSync')
|
|
6
6
|
|
|
7
7
|
const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
|
|
8
8
|
const PRIVATE_KEY_SCHEMA = 'DOTENV_PRIVATE_KEY'
|
|
@@ -25,7 +25,7 @@ function publicKeyNameFromEnvSrc (envParsed) {
|
|
|
25
25
|
|
|
26
26
|
function keyValuesFromEnvSrc (src, privateKeyName = null, opts = {}) {
|
|
27
27
|
let keysFilepath = opts.keysFilepath || null
|
|
28
|
-
const
|
|
28
|
+
const noArmor = opts.noArmor === true
|
|
29
29
|
const processEnv = opts.processEnv || process.env
|
|
30
30
|
const envParsed = dotenvParse(src)
|
|
31
31
|
|
|
@@ -37,6 +37,7 @@ function keyValuesFromEnvSrc (src, privateKeyName = null, opts = {}) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
let privateKeyValue = null
|
|
40
|
+
let privateKeySource = null
|
|
40
41
|
if (privateKeyName) {
|
|
41
42
|
privateKeyValue = readProcessKey(processEnv, privateKeyName)
|
|
42
43
|
|
|
@@ -51,16 +52,22 @@ function keyValuesFromEnvSrc (src, privateKeyName = null, opts = {}) {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
if (!
|
|
55
|
-
const kp =
|
|
55
|
+
if (!noArmor && !privateKeyValue && publicKeyValue && publicKeyValue.length > 0) {
|
|
56
|
+
const kp = armorKeypairSync(publicKeyValue)
|
|
56
57
|
privateKeyValue = kp.privateKey
|
|
58
|
+
privateKeySource = 'armor'
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
const result = {
|
|
60
62
|
publicKeyValue: publicKeyValue || null,
|
|
61
63
|
privateKeyValue: privateKeyValue || null,
|
|
62
64
|
privateKeyName: privateKeyName || null
|
|
63
65
|
}
|
|
66
|
+
if (privateKeySource) {
|
|
67
|
+
result.privateKeySource = privateKeySource
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return result
|
|
64
71
|
}
|
|
65
72
|
|
|
66
73
|
module.exports = keyValuesFromEnvSrc
|
|
@@ -5,7 +5,7 @@ const dotenvParse = require('./../dotenvParse')
|
|
|
5
5
|
const keyNames = require('./keyNames')
|
|
6
6
|
const readProcessKey = require('./readProcessKey')
|
|
7
7
|
const readFileKeySync = require('./readFileKeySync')
|
|
8
|
-
const
|
|
8
|
+
const armorKeypairSync = require('../cryptography/armorKeypairSync')
|
|
9
9
|
|
|
10
10
|
function invertForPrivateKeyName (filepath) {
|
|
11
11
|
const PUBLIC_KEY_SCHEMA = 'DOTENV_PUBLIC_KEY'
|
|
@@ -34,13 +34,14 @@ function invertForPrivateKeyName (filepath) {
|
|
|
34
34
|
|
|
35
35
|
function keyValuesSync (filepath, opts = {}) {
|
|
36
36
|
let keysFilepath = opts.keysFilepath || null
|
|
37
|
-
const
|
|
37
|
+
const noArmor = opts.noArmor === true
|
|
38
38
|
const names = keyNames(filepath)
|
|
39
39
|
const publicKeyName = names.publicKeyName // DOTENV_PUBLIC_KEY_${ENVIRONMENT}
|
|
40
40
|
let privateKeyName = names.privateKeyName // DOTENV_PRIVATE_KEY_${ENVIRONMENT}
|
|
41
41
|
|
|
42
42
|
let publicKey = null
|
|
43
43
|
let privateKey = null
|
|
44
|
+
let privateKeySource = null
|
|
44
45
|
|
|
45
46
|
// public key: process.env first, then .env*
|
|
46
47
|
publicKey = readProcessKey(publicKeyName)
|
|
@@ -70,21 +71,27 @@ function keyValuesSync (filepath, opts = {}) {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
//
|
|
74
|
-
if (!
|
|
75
|
-
const
|
|
74
|
+
// armor
|
|
75
|
+
if (!noArmor && !privateKey && publicKey && publicKey.length > 0) {
|
|
76
|
+
const armorOptions = { envFilepath: filepath }
|
|
76
77
|
if (opts.noSpinner) {
|
|
77
|
-
|
|
78
|
+
armorOptions.noSpinner = true
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
const kp =
|
|
81
|
+
const kp = armorKeypairSync(publicKey, armorOptions)
|
|
81
82
|
privateKey = kp.privateKey
|
|
83
|
+
privateKeySource = 'armor'
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
|
|
86
|
+
const result = {
|
|
85
87
|
publicKeyValue: publicKey || null, // important to make sure name is rendered
|
|
86
88
|
privateKeyValue: privateKey || null // important to make sure name is rendered
|
|
87
89
|
}
|
|
90
|
+
if (privateKeySource) {
|
|
91
|
+
result.privateKeySource = privateKeySource
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result
|
|
88
95
|
}
|
|
89
96
|
|
|
90
97
|
module.exports = keyValuesSync
|