@dotenvx/dotenvx 1.72.0 → 1.73.1
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 +15 -1
- package/README.md +1 -1
- package/package.json +1 -2
- package/src/cli/actions/armor/down.js +37 -0
- package/src/cli/actions/armor/move.js +42 -0
- package/src/cli/actions/armor/pull.js +37 -0
- package/src/cli/actions/armor/push.js +37 -0
- package/src/cli/actions/armor/up.js +37 -0
- package/src/cli/actions/login.js +0 -1
- package/src/cli/commands/armor.js +72 -0
- package/src/cli/dotenvx.js +3 -0
- package/src/db/session.js +90 -22
- package/src/lib/api/getAccount.js +32 -0
- package/src/lib/api/postArmorDown.js +48 -0
- package/src/lib/api/postArmorMove.js +48 -0
- package/src/lib/api/postArmorPull.js +48 -0
- package/src/lib/api/postArmorPush.js +48 -0
- package/src/lib/api/postArmorUp.js +51 -0
- package/src/lib/api/postKeypair.js +60 -0
- package/src/lib/helpers/armoredKeyDisplay.js +10 -0
- package/src/lib/helpers/cryptography/armorKeypair.js +32 -11
- package/src/lib/helpers/cryptography/armorKeypairSync.js +48 -7
- package/src/lib/helpers/cryptography/provision.js +2 -2
- package/src/lib/helpers/cryptography/provisionSync.js +2 -2
- package/src/lib/helpers/keyResolution/index.js +1 -1
- package/src/lib/helpers/keyResolution/{keyNames.js → keyNamesForEnvFile.js} +2 -2
- package/src/lib/helpers/keyResolution/keyValues.js +2 -2
- package/src/lib/helpers/keyResolution/keyValuesSync.js +2 -2
- package/src/lib/helpers/keypairMetadata.js +77 -0
- package/src/lib/helpers/readEnvKey.js +31 -0
- package/src/lib/helpers/removeEnvKey.js +50 -0
- package/src/lib/helpers/sanitizeCommandForMetadata.js +64 -0
- package/src/lib/helpers/teamChoicesFromMeta.js +8 -0
- package/src/lib/helpers/upsertEnvKey.js +61 -0
- package/src/lib/services/armorDown.js +71 -0
- package/src/lib/services/armorKeypair.js +156 -0
- package/src/lib/services/armorMove.js +54 -0
- package/src/lib/services/armorPull.js +71 -0
- package/src/lib/services/armorPush.js +76 -0
- package/src/lib/services/armorUp.js +73 -0
- package/src/lib/services/decrypt.js +2 -2
- package/src/lib/services/encrypt.js +2 -2
- package/src/lib/services/keypair.js +5 -7
- package/src/lib/services/loginPoll.js +1 -0
- package/src/lib/services/rotate.js +2 -2
- package/src/lib/services/run.js +3 -3
- package/src/lib/services/sets.js +3 -3
- package/src/lib/extensions/armor.js +0 -204
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
function escapeForRegex (value) {
|
|
5
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function upsertEnvKey (key, value, keysFilepath = '.env.keys') {
|
|
9
|
+
const resolvedKeysFilepath = path.resolve(keysFilepath)
|
|
10
|
+
const keyValueLine = `${key}=${value}`
|
|
11
|
+
const created = !fs.existsSync(resolvedKeysFilepath)
|
|
12
|
+
|
|
13
|
+
let src = ''
|
|
14
|
+
if (!created) {
|
|
15
|
+
src = fs.readFileSync(resolvedKeysFilepath, 'utf8')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const eol = src.includes('\r\n') ? '\r\n' : '\n'
|
|
19
|
+
const keyPattern = new RegExp(`^\\s*(?:export\\s+)?${escapeForRegex(key)}\\s*=`)
|
|
20
|
+
const lines = src.length > 0 ? src.split(/\r?\n/) : []
|
|
21
|
+
|
|
22
|
+
while (lines.length > 0 && lines[lines.length - 1] === '') {
|
|
23
|
+
lines.pop()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let replaced = false
|
|
27
|
+
const nextLines = []
|
|
28
|
+
|
|
29
|
+
for (const line of lines) {
|
|
30
|
+
if (keyPattern.test(line)) {
|
|
31
|
+
if (!replaced) {
|
|
32
|
+
nextLines.push(keyValueLine)
|
|
33
|
+
replaced = true
|
|
34
|
+
}
|
|
35
|
+
continue
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
nextLines.push(line)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!replaced) {
|
|
42
|
+
nextLines.push(keyValueLine)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const nextSrc = `${nextLines.join(eol)}${eol}`
|
|
46
|
+
const changed = created || nextSrc !== src
|
|
47
|
+
|
|
48
|
+
if (changed) {
|
|
49
|
+
fs.writeFileSync(resolvedKeysFilepath, nextSrc, 'utf8')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
changed,
|
|
54
|
+
key,
|
|
55
|
+
value,
|
|
56
|
+
created,
|
|
57
|
+
filepath: keysFilepath
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = upsertEnvKey
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const prompts = require('../helpers/prompts')
|
|
2
|
+
const PostArmorDown = require('../api/postArmorDown')
|
|
3
|
+
const keyNamesForEnvFile = require('../helpers/keyResolution/keyNamesForEnvFile')
|
|
4
|
+
const upsertEnvKey = require('../helpers/upsertEnvKey')
|
|
5
|
+
const readEnvKey = require('../helpers/readEnvKey')
|
|
6
|
+
const teamChoicesFromMeta = require('../helpers/teamChoicesFromMeta')
|
|
7
|
+
|
|
8
|
+
class ArmorDown {
|
|
9
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env', team = undefined) {
|
|
10
|
+
this.hostname = hostname
|
|
11
|
+
this.token = token
|
|
12
|
+
this.devicePublicKey = devicePublicKey
|
|
13
|
+
this.envFile = envFile
|
|
14
|
+
this.team = team
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run () {
|
|
18
|
+
const hostname = this.hostname
|
|
19
|
+
const token = this.token
|
|
20
|
+
const devicePublicKey = this.devicePublicKey
|
|
21
|
+
const envFile = this.envFile
|
|
22
|
+
const team = this.team
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
publicKeyName,
|
|
26
|
+
privateKeyName
|
|
27
|
+
} = keyNamesForEnvFile(envFile)
|
|
28
|
+
|
|
29
|
+
const publicKey = readEnvKey(publicKeyName, envFile, { strict: true, ignore: ['MISSING_PRIVATE_KEY'] })
|
|
30
|
+
let json
|
|
31
|
+
|
|
32
|
+
if (team) {
|
|
33
|
+
json = await new PostArmorDown(hostname, token, devicePublicKey, publicKey, team).run()
|
|
34
|
+
} else {
|
|
35
|
+
try {
|
|
36
|
+
json = await new PostArmorDown(hostname, token, devicePublicKey, publicKey, undefined).run()
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error.code !== 'DOTENVX_TEAM_REQUIRED') {
|
|
39
|
+
throw error
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const choices = teamChoicesFromMeta(error.meta)
|
|
43
|
+
|
|
44
|
+
let team = choices[0].value
|
|
45
|
+
if (choices.length > 1) {
|
|
46
|
+
team = await prompts.select({
|
|
47
|
+
message: 'Select team',
|
|
48
|
+
choices
|
|
49
|
+
}, {
|
|
50
|
+
input: process.stdin,
|
|
51
|
+
output: process.stderr
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
json = await new PostArmorDown(hostname, token, devicePublicKey, publicKey, team).run()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
upsertEnvKey(privateKeyName, json.private_key)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
...json,
|
|
63
|
+
changed: json.changed,
|
|
64
|
+
privateKeyName,
|
|
65
|
+
privateKeyValue: json.private_key,
|
|
66
|
+
publicKeyValue: publicKey
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = ArmorDown
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const prompts = require('../helpers/prompts')
|
|
2
|
+
const PostKeypair = require('../api/postKeypair')
|
|
3
|
+
const keypairMetadata = require('../helpers/keypairMetadata')
|
|
4
|
+
const teamChoicesFromMeta = require('../helpers/teamChoicesFromMeta')
|
|
5
|
+
|
|
6
|
+
const ACCESS_APPROVAL_REQUIRED = 'ACCESS_APPROVAL_REQUIRED'
|
|
7
|
+
const ACCESS_APPROVAL_PENDING = 'ACCESS_APPROVAL_PENDING'
|
|
8
|
+
const ACCESS_PENDING = 'ACCESS_PENDING'
|
|
9
|
+
const POLL_INTERVAL = 1000
|
|
10
|
+
const POLL_TIMEOUT = 5 * 60 * 1000
|
|
11
|
+
|
|
12
|
+
function grantTokenFromError (error) {
|
|
13
|
+
return error.meta && error.meta.grant_token
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isAccessApprovalRequired (error) {
|
|
17
|
+
return error.code === ACCESS_APPROVAL_REQUIRED
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isAccessPending (error) {
|
|
21
|
+
return error.code === ACCESS_PENDING || error.code === ACCESS_APPROVAL_PENDING
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function approvalUriFromError (error) {
|
|
25
|
+
if (error.meta) {
|
|
26
|
+
return error.meta.approval_uri
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return error.json && error.json.error && error.json.error.approval_uri
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function sleep (ms) {
|
|
33
|
+
await new Promise(resolve => setTimeout(resolve, ms))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function approvalTimeoutError () {
|
|
37
|
+
const code = 'ACCESS_APPROVAL_TIMEOUT'
|
|
38
|
+
const error = new Error(`[${code}] approval timed out after 5 minutes`)
|
|
39
|
+
error.code = code
|
|
40
|
+
return error
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
class ArmorKeypair {
|
|
44
|
+
constructor (hostname, token, devicePublicKey, publicKey, options = {}) {
|
|
45
|
+
this.hostname = hostname
|
|
46
|
+
this.token = token
|
|
47
|
+
this.devicePublicKey = devicePublicKey
|
|
48
|
+
this.publicKey = publicKey
|
|
49
|
+
this.team = options.team
|
|
50
|
+
this.envFile = options.envFile || '.env'
|
|
51
|
+
this.metadata = options.metadata
|
|
52
|
+
this.onApprovalRequired = null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async request (team, metadata, grantToken) {
|
|
56
|
+
if (grantToken !== undefined) {
|
|
57
|
+
return await new PostKeypair(
|
|
58
|
+
this.hostname,
|
|
59
|
+
this.token,
|
|
60
|
+
this.devicePublicKey,
|
|
61
|
+
this.publicKey,
|
|
62
|
+
team,
|
|
63
|
+
metadata,
|
|
64
|
+
grantToken
|
|
65
|
+
).run()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return await new PostKeypair(
|
|
69
|
+
this.hostname,
|
|
70
|
+
this.token,
|
|
71
|
+
this.devicePublicKey,
|
|
72
|
+
this.publicKey,
|
|
73
|
+
team,
|
|
74
|
+
metadata
|
|
75
|
+
).run()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async requestWithApprovalPolling (team, metadata) {
|
|
79
|
+
try {
|
|
80
|
+
return await this.request(team, metadata)
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (!isAccessApprovalRequired(error)) {
|
|
83
|
+
throw error
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const grantToken = grantTokenFromError(error)
|
|
87
|
+
if (!grantToken) {
|
|
88
|
+
throw error
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const approvalUri = approvalUriFromError(error)
|
|
92
|
+
if (!approvalUri) {
|
|
93
|
+
throw error
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (this.onApprovalRequired) {
|
|
97
|
+
this.onApprovalRequired({ approvalUri, code: error.code })
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return await this.poll(team, metadata, grantToken)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async poll (team, metadata, grantToken) {
|
|
105
|
+
const startedAt = Date.now()
|
|
106
|
+
|
|
107
|
+
while (true) {
|
|
108
|
+
try {
|
|
109
|
+
return await this.request(team, metadata, grantToken)
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if (!isAccessPending(error)) {
|
|
112
|
+
throw error
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (Date.now() - startedAt >= POLL_TIMEOUT) {
|
|
116
|
+
throw approvalTimeoutError()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
await sleep(POLL_INTERVAL)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async run () {
|
|
125
|
+
const metadata = keypairMetadata(this.envFile, this.metadata)
|
|
126
|
+
|
|
127
|
+
if (this.team) {
|
|
128
|
+
return await this.requestWithApprovalPolling(this.team, metadata)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
return await this.requestWithApprovalPolling(undefined, metadata)
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error.code !== 'DOTENVX_TEAM_REQUIRED') {
|
|
135
|
+
throw error
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const choices = teamChoicesFromMeta(error.meta)
|
|
139
|
+
|
|
140
|
+
let team = choices[0].value
|
|
141
|
+
if (choices.length > 1) {
|
|
142
|
+
team = await prompts.select({
|
|
143
|
+
message: 'Select team',
|
|
144
|
+
choices
|
|
145
|
+
}, {
|
|
146
|
+
input: process.stdin,
|
|
147
|
+
output: process.stderr
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return await this.requestWithApprovalPolling(team, metadata)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = ArmorKeypair
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const prompts = require('../helpers/prompts')
|
|
2
|
+
const PostArmorMove = require('../api/postArmorMove')
|
|
3
|
+
const GetAccount = require('../api/getAccount')
|
|
4
|
+
const keyNamesForEnvFile = require('../helpers/keyResolution/keyNamesForEnvFile')
|
|
5
|
+
const readEnvKey = require('../helpers/readEnvKey')
|
|
6
|
+
|
|
7
|
+
class ArmorMove {
|
|
8
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env') {
|
|
9
|
+
this.hostname = hostname
|
|
10
|
+
this.token = token
|
|
11
|
+
this.devicePublicKey = devicePublicKey
|
|
12
|
+
this.envFile = envFile
|
|
13
|
+
|
|
14
|
+
this.team = null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run () {
|
|
18
|
+
const hostname = this.hostname
|
|
19
|
+
const token = this.token
|
|
20
|
+
const devicePublicKey = this.devicePublicKey
|
|
21
|
+
const envFile = this.envFile
|
|
22
|
+
let team = this.team
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
publicKeyName,
|
|
26
|
+
privateKeyName
|
|
27
|
+
} = keyNamesForEnvFile(envFile)
|
|
28
|
+
const publicKey = readEnvKey(publicKeyName, envFile, { strict: true, ignore: ['MISSING_PRIVATE_KEY'] })
|
|
29
|
+
|
|
30
|
+
const accountJson = await new GetAccount(hostname, token).run()
|
|
31
|
+
const choices = accountJson.organizations.map(o => ({
|
|
32
|
+
name: o.provider_slug,
|
|
33
|
+
value: o.provider_slug
|
|
34
|
+
}))
|
|
35
|
+
team = await prompts.select({
|
|
36
|
+
message: 'Select team',
|
|
37
|
+
choices
|
|
38
|
+
}, {
|
|
39
|
+
input: process.stdin,
|
|
40
|
+
output: process.stderr
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const json = await new PostArmorMove(hostname, token, devicePublicKey, publicKey, team).run()
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
...json,
|
|
47
|
+
privateKeyName,
|
|
48
|
+
privateKeyValue: json.private_key,
|
|
49
|
+
publicKeyValue: publicKey
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = ArmorMove
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const prompts = require('../helpers/prompts')
|
|
2
|
+
const PostArmorPull = require('../api/postArmorPull')
|
|
3
|
+
const upsertEnvKey = require('../helpers/upsertEnvKey')
|
|
4
|
+
const keyNamesForEnvFile = require('../helpers/keyResolution/keyNamesForEnvFile')
|
|
5
|
+
const readEnvKey = require('../helpers/readEnvKey')
|
|
6
|
+
const teamChoicesFromMeta = require('../helpers/teamChoicesFromMeta')
|
|
7
|
+
|
|
8
|
+
class ArmorPull {
|
|
9
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env', team = undefined) {
|
|
10
|
+
this.hostname = hostname
|
|
11
|
+
this.token = token
|
|
12
|
+
this.devicePublicKey = devicePublicKey
|
|
13
|
+
this.envFile = envFile
|
|
14
|
+
this.team = team
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run () {
|
|
18
|
+
const hostname = this.hostname
|
|
19
|
+
const token = this.token
|
|
20
|
+
const devicePublicKey = this.devicePublicKey
|
|
21
|
+
const envFile = this.envFile
|
|
22
|
+
const team = this.team
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
publicKeyName,
|
|
26
|
+
privateKeyName
|
|
27
|
+
} = keyNamesForEnvFile(envFile)
|
|
28
|
+
|
|
29
|
+
const publicKey = readEnvKey(publicKeyName, envFile, { strict: true, ignore: ['MISSING_PRIVATE_KEY'] })
|
|
30
|
+
let json
|
|
31
|
+
|
|
32
|
+
if (team) {
|
|
33
|
+
json = await new PostArmorPull(hostname, token, devicePublicKey, publicKey, team).run()
|
|
34
|
+
} else {
|
|
35
|
+
try {
|
|
36
|
+
json = await new PostArmorPull(hostname, token, devicePublicKey, publicKey, undefined).run()
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error.code !== 'DOTENVX_TEAM_REQUIRED') {
|
|
39
|
+
throw error
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const choices = teamChoicesFromMeta(error.meta)
|
|
43
|
+
|
|
44
|
+
let team = choices[0].value
|
|
45
|
+
if (choices.length > 1) {
|
|
46
|
+
team = await prompts.select({
|
|
47
|
+
message: 'Select team',
|
|
48
|
+
choices
|
|
49
|
+
}, {
|
|
50
|
+
input: process.stdin,
|
|
51
|
+
output: process.stderr
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
json = await new PostArmorPull(hostname, token, devicePublicKey, publicKey, team).run()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const result = upsertEnvKey(privateKeyName, json.private_key)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
...json,
|
|
63
|
+
changed: result.changed,
|
|
64
|
+
privateKeyName,
|
|
65
|
+
privateKeyValue: json.private_key,
|
|
66
|
+
publicKeyValue: publicKey
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = ArmorPull
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const { PrivateKey } = require('eciesjs')
|
|
2
|
+
const prompts = require('../helpers/prompts')
|
|
3
|
+
const PostArmorPush = require('../api/postArmorPush')
|
|
4
|
+
const keyNamesForEnvFile = require('../helpers/keyResolution/keyNamesForEnvFile')
|
|
5
|
+
const readEnvKey = require('../helpers/readEnvKey')
|
|
6
|
+
const teamChoicesFromMeta = require('../helpers/teamChoicesFromMeta')
|
|
7
|
+
|
|
8
|
+
function publicKeyFromPrivateKey (privateKey) {
|
|
9
|
+
try {
|
|
10
|
+
return new PrivateKey(Buffer.from(privateKey, 'hex')).publicKey.toHex()
|
|
11
|
+
} catch {
|
|
12
|
+
return ''
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class ArmorPush {
|
|
17
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env', team = undefined) {
|
|
18
|
+
this.hostname = hostname
|
|
19
|
+
this.token = token
|
|
20
|
+
this.devicePublicKey = devicePublicKey
|
|
21
|
+
this.envFile = envFile
|
|
22
|
+
this.team = team
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async run () {
|
|
26
|
+
const hostname = this.hostname
|
|
27
|
+
const token = this.token
|
|
28
|
+
const devicePublicKey = this.devicePublicKey
|
|
29
|
+
const envFile = this.envFile
|
|
30
|
+
const team = this.team
|
|
31
|
+
|
|
32
|
+
const { privateKeyName } = keyNamesForEnvFile(envFile)
|
|
33
|
+
|
|
34
|
+
const privateKey = readEnvKey(privateKeyName, '.env.keys', { strict: true })
|
|
35
|
+
const publicKey = publicKeyFromPrivateKey(privateKey)
|
|
36
|
+
|
|
37
|
+
let json
|
|
38
|
+
|
|
39
|
+
if (team) {
|
|
40
|
+
json = await new PostArmorPush(hostname, token, devicePublicKey, privateKey, team).run()
|
|
41
|
+
} else {
|
|
42
|
+
try {
|
|
43
|
+
json = await new PostArmorPush(hostname, token, devicePublicKey, privateKey, undefined).run()
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error.code !== 'DOTENVX_TEAM_REQUIRED') {
|
|
46
|
+
throw error
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const choices = teamChoicesFromMeta(error.meta)
|
|
50
|
+
|
|
51
|
+
let team = choices[0].value
|
|
52
|
+
if (choices.length > 1) {
|
|
53
|
+
team = await prompts.select({
|
|
54
|
+
message: 'Select team',
|
|
55
|
+
choices
|
|
56
|
+
}, {
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stderr
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
json = await new PostArmorPush(hostname, token, devicePublicKey, privateKey, team).run()
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
...json,
|
|
68
|
+
changed: json.changed,
|
|
69
|
+
privateKeyName,
|
|
70
|
+
privateKeyValue: json.private_key,
|
|
71
|
+
publicKeyValue: publicKey
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = ArmorPush
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const prompts = require('../helpers/prompts')
|
|
2
|
+
const PostArmorUp = require('../api/postArmorUp')
|
|
3
|
+
const keyNamesForEnvFile = require('../helpers/keyResolution/keyNamesForEnvFile')
|
|
4
|
+
const removeEnvKey = require('../helpers/removeEnvKey')
|
|
5
|
+
const readEnvKey = require('../helpers/readEnvKey')
|
|
6
|
+
const teamChoicesFromMeta = require('../helpers/teamChoicesFromMeta')
|
|
7
|
+
|
|
8
|
+
class ArmorUp {
|
|
9
|
+
constructor (hostname, token, devicePublicKey, envFile = '.env', team = undefined) {
|
|
10
|
+
this.hostname = hostname
|
|
11
|
+
this.token = token
|
|
12
|
+
this.devicePublicKey = devicePublicKey
|
|
13
|
+
this.envFile = envFile
|
|
14
|
+
this.team = team
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async run () {
|
|
18
|
+
const hostname = this.hostname
|
|
19
|
+
const token = this.token
|
|
20
|
+
const devicePublicKey = this.devicePublicKey
|
|
21
|
+
const envFile = this.envFile
|
|
22
|
+
const team = this.team
|
|
23
|
+
|
|
24
|
+
const {
|
|
25
|
+
publicKeyName,
|
|
26
|
+
privateKeyName
|
|
27
|
+
} = keyNamesForEnvFile(envFile)
|
|
28
|
+
|
|
29
|
+
const publicKey = readEnvKey(publicKeyName, envFile, { strict: true, ignore: ['MISSING_PRIVATE_KEY'] })
|
|
30
|
+
const privateKey = readEnvKey(privateKeyName, '.env.keys', { strict: true, ignore: ['MISSING_KEY'] })
|
|
31
|
+
|
|
32
|
+
let json
|
|
33
|
+
|
|
34
|
+
if (team) {
|
|
35
|
+
json = await new PostArmorUp(hostname, token, devicePublicKey, publicKey, privateKey, team).run()
|
|
36
|
+
} else {
|
|
37
|
+
try {
|
|
38
|
+
json = await new PostArmorUp(hostname, token, devicePublicKey, publicKey, privateKey, undefined).run()
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (error.code !== 'DOTENVX_TEAM_REQUIRED') {
|
|
41
|
+
throw error
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const choices = teamChoicesFromMeta(error.meta)
|
|
45
|
+
|
|
46
|
+
let team = choices[0].value
|
|
47
|
+
if (choices.length > 1) {
|
|
48
|
+
team = await prompts.select({
|
|
49
|
+
message: 'Select team',
|
|
50
|
+
choices
|
|
51
|
+
}, {
|
|
52
|
+
input: process.stdin,
|
|
53
|
+
output: process.stderr
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
json = await new PostArmorUp(hostname, token, devicePublicKey, publicKey, privateKey, team).run()
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
removeEnvKey(privateKeyName)
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
...json,
|
|
65
|
+
changed: json.changed,
|
|
66
|
+
privateKeyName,
|
|
67
|
+
privateKeyValue: json.private_key,
|
|
68
|
+
publicKeyValue: publicKey
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = ArmorUp
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
} = require('./../helpers/envResolution')
|
|
12
12
|
|
|
13
13
|
const {
|
|
14
|
-
|
|
14
|
+
keyNamesForEnvFile,
|
|
15
15
|
keyValues
|
|
16
16
|
} = require('./../helpers/keyResolution')
|
|
17
17
|
|
|
@@ -77,7 +77,7 @@ class Decrypt {
|
|
|
77
77
|
let envSrc = await fsx.readFileX(filepath, { encoding })
|
|
78
78
|
const envParsed = dotenvParse(envSrc, false, false, true)
|
|
79
79
|
|
|
80
|
-
const { privateKeyName } =
|
|
80
|
+
const { privateKeyName } = keyNamesForEnvFile(envFilepath)
|
|
81
81
|
const { privateKeyValue, privateKeySource } = await keyValues(envFilepath, {
|
|
82
82
|
keysFilepath: this.envKeysFilepath,
|
|
83
83
|
noArmor: this.noArmor,
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
} = require('./../helpers/envResolution')
|
|
12
12
|
|
|
13
13
|
const {
|
|
14
|
-
|
|
14
|
+
keyNamesForEnvFile,
|
|
15
15
|
keyValues
|
|
16
16
|
} = require('./../helpers/keyResolution')
|
|
17
17
|
|
|
@@ -102,7 +102,7 @@ class Encrypt {
|
|
|
102
102
|
let publicKey
|
|
103
103
|
let privateKey
|
|
104
104
|
|
|
105
|
-
const { publicKeyName, privateKeyName } =
|
|
105
|
+
const { publicKeyName, privateKeyName } = keyNamesForEnvFile(envFilepath)
|
|
106
106
|
const { publicKeyValue, privateKeyValue } = await keyValues(envFilepath, {
|
|
107
107
|
keysFilepath: this.envKeysFilepath,
|
|
108
108
|
noArmor: this.noArmor,
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
keyValuesSync
|
|
5
|
-
} = require('./../helpers/keyResolution')
|
|
1
|
+
const keyNamesForEnvFile = require('./../helpers/keyResolution/keyNamesForEnvFile')
|
|
2
|
+
const keyValues = require('./../helpers/keyResolution/keyValues')
|
|
3
|
+
const keyValuesSync = require('./../helpers/keyResolution/keyValuesSync')
|
|
6
4
|
|
|
7
5
|
class Keypair {
|
|
8
6
|
constructor (envFile = '.env', envKeysFilepath = null, noArmor = false, options = {}) {
|
|
@@ -17,7 +15,7 @@ class Keypair {
|
|
|
17
15
|
|
|
18
16
|
const filepaths = this._filepaths()
|
|
19
17
|
for (const filepath of filepaths) {
|
|
20
|
-
const { publicKeyName, privateKeyName } =
|
|
18
|
+
const { publicKeyName, privateKeyName } = keyNamesForEnvFile(filepath)
|
|
21
19
|
const { publicKeyValue, privateKeyValue } = keyValuesSync(filepath, {
|
|
22
20
|
keysFilepath: this.envKeysFilepath,
|
|
23
21
|
noArmor: this.noArmor,
|
|
@@ -36,7 +34,7 @@ class Keypair {
|
|
|
36
34
|
|
|
37
35
|
const filepaths = this._filepaths()
|
|
38
36
|
for (const filepath of filepaths) {
|
|
39
|
-
const { publicKeyName, privateKeyName } =
|
|
37
|
+
const { publicKeyName, privateKeyName } = keyNamesForEnvFile(filepath)
|
|
40
38
|
const { publicKeyValue, privateKeyValue } = await keyValues(filepath, {
|
|
41
39
|
keysFilepath: this.envKeysFilepath,
|
|
42
40
|
noArmor: this.noArmor,
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
} = require('./../helpers/envResolution')
|
|
12
12
|
|
|
13
13
|
const {
|
|
14
|
-
|
|
14
|
+
keyNamesForEnvFile,
|
|
15
15
|
keyValues
|
|
16
16
|
} = require('./../helpers/keyResolution')
|
|
17
17
|
|
|
@@ -83,7 +83,7 @@ class Rotate {
|
|
|
83
83
|
let envSrc = await fsx.readFileX(filepath, { encoding })
|
|
84
84
|
const envParsed = dotenvParse(envSrc, false, false, true)
|
|
85
85
|
|
|
86
|
-
const { publicKeyName, privateKeyName } =
|
|
86
|
+
const { publicKeyName, privateKeyName } = keyNamesForEnvFile(envFilepath)
|
|
87
87
|
const { privateKeyValue } = await keyValues(envFilepath, {
|
|
88
88
|
keysFilepath: this.envKeysFilepath,
|
|
89
89
|
noArmor: this.noArmor,
|
package/src/lib/services/run.js
CHANGED
|
@@ -10,7 +10,7 @@ const detectEncoding = require('./../helpers/detectEncoding')
|
|
|
10
10
|
const detectEncodingSync = require('./../helpers/detectEncodingSync')
|
|
11
11
|
|
|
12
12
|
const {
|
|
13
|
-
|
|
13
|
+
keyNamesForEnvFile,
|
|
14
14
|
keyValues,
|
|
15
15
|
keyValuesSync,
|
|
16
16
|
keyValuesFromEnvSrc
|
|
@@ -147,7 +147,7 @@ class Run {
|
|
|
147
147
|
const src = fsx.readFileXSync(filepath, { encoding })
|
|
148
148
|
this.readableFilepaths.add(envFilepath)
|
|
149
149
|
|
|
150
|
-
const { privateKeyName } =
|
|
150
|
+
const { privateKeyName } = keyNamesForEnvFile(filepath)
|
|
151
151
|
const { privateKeyValue, privateKeySource } = keyValuesSync(filepath, {
|
|
152
152
|
keysFilepath: this.envKeysFilepath,
|
|
153
153
|
noArmor: this.noArmor,
|
|
@@ -202,7 +202,7 @@ class Run {
|
|
|
202
202
|
const src = await fsx.readFileX(filepath, { encoding })
|
|
203
203
|
this.readableFilepaths.add(envFilepath)
|
|
204
204
|
|
|
205
|
-
const { privateKeyName } =
|
|
205
|
+
const { privateKeyName } = keyNamesForEnvFile(filepath)
|
|
206
206
|
const { privateKeyValue, privateKeySource } = await keyValues(filepath, {
|
|
207
207
|
keysFilepath: this.envKeysFilepath,
|
|
208
208
|
noArmor: this.noArmor,
|