@dotenvx/dotenvx 2.2.1 → 2.3.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 +21 -1
- package/README.md +99 -67
- package/package.json +2 -2
- package/src/cli/actions/decrypt.js +2 -3
- package/src/cli/actions/encrypt.js +2 -3
- package/src/cli/actions/get.js +2 -3
- package/src/cli/actions/keychain/up.js +2 -2
- package/src/cli/actions/keypair.js +2 -3
- package/src/cli/actions/lock/down.js +74 -0
- package/src/cli/actions/lock/up.js +80 -0
- package/src/cli/actions/run.js +2 -3
- package/src/cli/actions/set.js +2 -3
- package/src/cli/commands/armor.js +19 -1
- package/src/cli/commands/lock.js +27 -0
- package/src/cli/commands/{keychain.js → native.js} +13 -13
- package/src/cli/dotenvx.js +16 -20
- package/src/db/session.js +7 -7
- package/src/lib/helpers/errors.js +13 -0
- package/src/lib/helpers/executeDynamic.js +1 -19
- package/src/lib/main.d.ts +9 -33
- package/src/lib/main.js +3 -3
- package/src/lib/providers/index.js +1 -1
- package/src/lib/services/keychainPull.js +1 -1
- package/src/lib/services/lockDown.js +157 -0
- package/src/lib/services/lockUp.js +150 -0
- package/src/cli/actions/normalizeArmorAliases.js +0 -9
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const { derive, publickeys, scan } = require('@dotenvx/primitives')
|
|
3
|
+
|
|
4
|
+
const Errors = require('../helpers/errors')
|
|
5
|
+
const upsertEnvKey = require('../helpers/upsertEnvKey')
|
|
6
|
+
|
|
7
|
+
function latestValues (parsed) {
|
|
8
|
+
const result = {}
|
|
9
|
+
|
|
10
|
+
for (const [key, values] of Object.entries(parsed)) {
|
|
11
|
+
result[key] = values[values.length - 1]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function privateKeyring (keysSrc) {
|
|
18
|
+
const { parsed } = scan(keysSrc)
|
|
19
|
+
const values = latestValues(parsed)
|
|
20
|
+
const keyring = {}
|
|
21
|
+
|
|
22
|
+
for (const [privateKeyName, privateKey] of Object.entries(values)) {
|
|
23
|
+
if (!privateKeyName.startsWith('DOTENV_PRIVATE_KEY')) continue
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const publicKey = derive(privateKey)
|
|
27
|
+
keyring[publicKey] = { privateKeyName, privateKeyValue: privateKey }
|
|
28
|
+
} catch {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return keyring
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function lockedKeyring (keysSrc) {
|
|
35
|
+
const { parsed } = scan(keysSrc)
|
|
36
|
+
const values = latestValues(parsed)
|
|
37
|
+
const keyring = {}
|
|
38
|
+
|
|
39
|
+
for (const [privateKeyName, privateKey] of Object.entries(values)) {
|
|
40
|
+
if (!privateKeyName.startsWith('DOTENV_PRIVATE_KEY')) continue
|
|
41
|
+
if (!privateKey.startsWith('locked:')) continue
|
|
42
|
+
|
|
43
|
+
const parts = privateKey.split(':')
|
|
44
|
+
if (parts.length < 3) continue
|
|
45
|
+
|
|
46
|
+
const publicKey = parts[1]
|
|
47
|
+
keyring[publicKey] = {
|
|
48
|
+
privateKeyName,
|
|
49
|
+
lockedPrivateKeyValue: privateKey,
|
|
50
|
+
publicKeyValue: publicKey
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return keyring
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class LockUp {
|
|
58
|
+
constructor (envFile = '.env', envKeysFile = '.env.keys') {
|
|
59
|
+
this.envFile = envFile
|
|
60
|
+
this.envKeysFile = envKeysFile
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
plan () {
|
|
64
|
+
const envFile = this.envFile
|
|
65
|
+
const envKeysFile = this.envKeysFile
|
|
66
|
+
|
|
67
|
+
const envSrc = fs.readFileSync(envFile, 'utf8')
|
|
68
|
+
const keysSrc = fs.readFileSync(envKeysFile, 'utf8')
|
|
69
|
+
const ring = privateKeyring(keysSrc)
|
|
70
|
+
const lockedRing = lockedKeyring(keysSrc)
|
|
71
|
+
const matches = []
|
|
72
|
+
const alreadyLocked = []
|
|
73
|
+
|
|
74
|
+
for (const publicKey of publickeys(envSrc)) {
|
|
75
|
+
const privateKey = ring[publicKey]
|
|
76
|
+
if (privateKey) {
|
|
77
|
+
matches.push({
|
|
78
|
+
privateKeyName: privateKey.privateKeyName,
|
|
79
|
+
privateKeyValue: privateKey.privateKeyValue,
|
|
80
|
+
publicKeyValue: publicKey
|
|
81
|
+
})
|
|
82
|
+
continue
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const lockedPrivateKey = lockedRing[publicKey]
|
|
86
|
+
if (lockedPrivateKey) {
|
|
87
|
+
alreadyLocked.push(lockedPrivateKey)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (matches.length < 1 && alreadyLocked.length < 1) {
|
|
92
|
+
throw new Errors({ key: 'DOTENV_PRIVATE_KEY' }).missingKey()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { matches, alreadyLocked }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
matches () {
|
|
99
|
+
const { matches } = this.plan()
|
|
100
|
+
|
|
101
|
+
if (matches.length < 1) {
|
|
102
|
+
throw new Errors({ key: 'DOTENV_PRIVATE_KEY' }).missingKey()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return matches
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
run (lockPrivateKey) {
|
|
109
|
+
if (!lockPrivateKey) {
|
|
110
|
+
throw new Error('missing lock private key function')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const envKeysFile = this.envKeysFile
|
|
114
|
+
const results = []
|
|
115
|
+
|
|
116
|
+
const { matches, alreadyLocked } = this.plan()
|
|
117
|
+
|
|
118
|
+
for (const privateKey of matches) {
|
|
119
|
+
const lockedPrivateKey = lockPrivateKey(privateKey.privateKeyValue, privateKey.publicKeyValue)
|
|
120
|
+
const result = upsertEnvKey(privateKey.privateKeyName, lockedPrivateKey, envKeysFile)
|
|
121
|
+
|
|
122
|
+
results.push({
|
|
123
|
+
changed: result.changed,
|
|
124
|
+
privateKeyName: privateKey.privateKeyName,
|
|
125
|
+
privateKeyValue: privateKey.privateKeyValue,
|
|
126
|
+
lockedPrivateKeyValue: lockedPrivateKey,
|
|
127
|
+
publicKeyValue: privateKey.publicKeyValue
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (const lockedPrivateKey of alreadyLocked) {
|
|
132
|
+
results.push({
|
|
133
|
+
changed: false,
|
|
134
|
+
privateKeyName: lockedPrivateKey.privateKeyName,
|
|
135
|
+
privateKeyValue: undefined,
|
|
136
|
+
lockedPrivateKeyValue: lockedPrivateKey.lockedPrivateKeyValue,
|
|
137
|
+
publicKeyValue: lockedPrivateKey.publicKeyValue,
|
|
138
|
+
alreadyLocked: true
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
changed: results.some(result => result.changed),
|
|
144
|
+
results
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = LockUp
|
|
150
|
+
module.exports.privateKeyring = privateKeyring
|