Comparing version 1.0.19 to 1.0.20
const fs = require('fs'); | ||
const { | ||
connectToWorkspace | ||
checkConnect | ||
} = require('../api'); | ||
@@ -9,3 +9,9 @@ const { | ||
/** | ||
* Establish connection with workspace with id [workspaceId]. Follow steps: | ||
* 1. Verify user's membership with workspace | ||
* 2. Record workspaceId into file .env.infisical | ||
* @param {Object} obj | ||
* @param {Object} obj.workspaceId - id of workspace to connect to | ||
*/ | ||
const connect = async ({ | ||
@@ -15,15 +21,24 @@ workspaceId | ||
// check workspace connection | ||
await connectToWorkspace({ workspaceId }); | ||
// create .env.infisical to store workspaceId | ||
await write({ | ||
fileName: '.env.infisical', | ||
content: workspaceId | ||
}); | ||
console.log('✅ Successfully established connection with workspace ' + workspaceId); | ||
process.exit(0); | ||
try { | ||
// check workspace connection | ||
const isConnected = await checkConnect({ workspaceId }); | ||
if (isConnected) { | ||
// create .env.infisical to store workspaceId | ||
await write({ | ||
fileName: '.env.infisical', | ||
content: workspaceId | ||
}); | ||
console.log('✅ Successfully established connection with workspace ' + workspaceId); | ||
process.exit(0); | ||
} else { | ||
throw new Error("Failed to connect to workspace with id " + workspaceId); | ||
} | ||
} catch (err) { | ||
console.error(err.message); | ||
process.exit(1); | ||
} | ||
} | ||
module.exports = connect; |
const netrc = require('netrc-rw'); | ||
const jsrp = require('jsrp'); | ||
const axios = require('axios'); | ||
const open = require('open'); | ||
const prompt = require('prompt-sync')(); | ||
@@ -13,7 +11,7 @@ const express = require('express'); | ||
const { | ||
decryptSymmetric | ||
} = require('../utilities/crypto'); | ||
authenticate | ||
} = require('../utilities/auth'); | ||
/** | ||
* Authenticate user via SRP protocol | ||
* Login user | ||
*/ | ||
@@ -29,71 +27,13 @@ const login = async () => { | ||
// login | ||
// login | ||
console.log('Logging in...'); | ||
const client = new jsrp.client(); | ||
client.init({ | ||
username: email, | ||
password, | ||
}, async () => { | ||
const clientPublicKey = client.getPublicKey(); | ||
let serverPublicKey, salt; | ||
try { | ||
const res = await axios.post(INFISICAL_URL + '/login1', { | ||
email, | ||
clientPublicKey | ||
}); | ||
serverPublicKey = res.data.serverPublicKey; | ||
salt = res.data.salt; | ||
} catch (err) { | ||
console.error(err); | ||
console.error("❌ Error: Failed to validate your login credentials"); | ||
process.exit(0); | ||
} | ||
client.setSalt(salt); | ||
client.setServerPublicKey(serverPublicKey); | ||
const clientProof = client.getProof(); // M1 | ||
let res; | ||
try { | ||
res = await axios.post(INFISICAL_URL + '/login2', { | ||
email, | ||
clientProof | ||
}); | ||
} catch (err) { | ||
console.error(err); | ||
console.error("❌ Error: Failed to validate your login credentials"); | ||
process.exit(0); | ||
} | ||
// decrypt private key | ||
const privateKey = decryptSymmetric({ | ||
ciphertext: res.data.encryptedPrivateKey, | ||
iv: res.data.iv, | ||
tag: res.data.tag, | ||
key: password.slice(0, 32).padStart(32, '0') | ||
}); | ||
// update authentication information on file | ||
updateNetRC({ | ||
host: LOGIN_HOST, | ||
login: email, | ||
password: res.data.token | ||
}); | ||
// update key information on file | ||
updateNetRC({ | ||
host: KEYS_HOST, | ||
login: res.data.publicKey, | ||
password: privateKey | ||
}); | ||
console.log('✅ Logged in as ' + email); | ||
process.exit(0); | ||
await authenticate({ | ||
email, | ||
password | ||
}); | ||
console.log('✅ Logged in as ' + email); | ||
process.exit(0); | ||
} catch (err) { | ||
console.log(err); | ||
console.error("❌ Error: Something went wrong while logging you in... Let's try that again"); | ||
console.error(err.message); | ||
process.exit(1); | ||
@@ -103,32 +43,2 @@ } | ||
/** | ||
* Overwrite NetRC file with new credentails. | ||
* @param {Object} obj | ||
* @param {String} obj.host - new host information | ||
* @param {String} obj.login - new username information | ||
* @param {String} obj.password - new password information | ||
*/ | ||
const updateNetRC = ({ | ||
host, | ||
login, | ||
password | ||
}) => { | ||
try { | ||
let credentials = netrc.host(host); | ||
// host exists | ||
netrc.host(host).login = login; | ||
netrc.host(host).password = password; | ||
netrc.write(); | ||
} catch (err) { | ||
// host doesn't exist | ||
netrc.addHost(host).password = password; | ||
netrc.write(); | ||
netrc.host(host).login = login; | ||
netrc.write(); | ||
} | ||
} | ||
module.exports = login; |
@@ -16,2 +16,5 @@ const { | ||
const { | ||
decryptSecrets | ||
} = require("../utilities/secret"); | ||
const { | ||
KEYS_HOST | ||
@@ -25,3 +28,4 @@ } = require('../variables'); | ||
* 3. Symmetrically decrypt secrets with key | ||
* @param {String} environment - dev, staging, or prod | ||
* @param {Object} obj | ||
* @param {String} obj.environment - dev, staging, or prod | ||
*/ | ||
@@ -35,7 +39,7 @@ const pull = async ({ | ||
const credentials = getCredentials({ host: KEYS_HOST }); | ||
console.log("Pulling file..."); | ||
console.log("⬇️ Pulling file..."); | ||
const secrets = await getSecrets({ workspaceId, environment }); | ||
console.log("Decrypting file..."); | ||
console.log("🔐 Decrypting file..."); | ||
@@ -51,28 +55,8 @@ // asymmetrically decrypt symmetric key with local private key | ||
// decrypt secrets with symmetric key | ||
let content = ''; | ||
secrets.secrets.forEach((sp, idx) => { | ||
const content = decryptSecrets({ | ||
secrets, | ||
key, | ||
format: "text" | ||
}); | ||
const secretKey = decryptSymmetric({ | ||
ciphertext: sp.secretKey.ciphertext, | ||
iv: sp.secretKey.iv, | ||
tag: sp.secretKey.tag, | ||
key | ||
}); | ||
const secretValue = decryptSymmetric({ | ||
ciphertext: sp.secretValue.ciphertext, | ||
iv: sp.secretValue.iv, | ||
tag: sp.secretValue.tag, | ||
key | ||
}); | ||
content += secretKey; | ||
content += '='; | ||
content += secretValue; | ||
if (idx < secrets.secrets.length) { | ||
content += '\n'; | ||
} | ||
}); | ||
write({ | ||
@@ -79,0 +63,0 @@ fileName: '.env', |
@@ -22,3 +22,4 @@ const path = require("path"); | ||
* 4. Package and send 2-3 to server | ||
* @param {String} environment - dev, staging, or prod | ||
* @param {Object} obj | ||
* @param {String} obj.environment - dev, staging, or prod | ||
*/ | ||
@@ -38,3 +39,3 @@ const push = async ({ | ||
console.log("Encrypting file..."); | ||
console.log("🔐 Encrypting file..."); | ||
@@ -89,3 +90,3 @@ let sharedKey = await getSharedKey({ workspaceId }); | ||
console.log("Generating access keys..."); | ||
console.log("🔑 Generating access keys..."); | ||
@@ -112,3 +113,3 @@ // obtain public keys of all receivers (i.e. members in workspace) | ||
console.log("Pushing file..."); | ||
console.log("⬆️ Pushing file..."); | ||
await uploadSecrets({ | ||
@@ -115,0 +116,0 @@ workspaceId, |
const axios = require("axios"); | ||
const netrc = require("netrc-rw"); | ||
const { INFISICAL_URL, LOGIN_HOST } = require("./variables"); | ||
const { getCredentials } = require("./utilities/auth"); | ||
const connectToWorkspace = async ({ workspaceId }) => { | ||
const credentials = getCredentials({ | ||
host: LOGIN_HOST, | ||
}); | ||
let response; | ||
try { | ||
response = await axios.get( | ||
INFISICAL_URL + "/membership/" + workspaceId + "/connect", | ||
{ | ||
headers: { | ||
Authorization: "Bearer " + credentials.password, | ||
}, | ||
} | ||
); | ||
} catch (err) { | ||
console.error( | ||
"❌ Error: Failed to connect to workspace with id " + workspaceId | ||
); | ||
process.exit(1); | ||
} | ||
}; | ||
const getWorkspaceKeys = async ({ workspaceId }) => { | ||
@@ -137,8 +116,43 @@ const credentials = getCredentials({ | ||
const checkConnect = async ({ workspaceId }) => { | ||
let response; | ||
try { | ||
const credentials = netrc.host(LOGIN_HOST); | ||
response = await axios.get( | ||
INFISICAL_URL + "/membership/" + workspaceId + "/connect", | ||
{ | ||
headers: { | ||
Authorization: "Bearer " + credentials.password, | ||
}, | ||
} | ||
); | ||
} catch (err) { | ||
return false; | ||
} | ||
return true; | ||
}; | ||
const checkAuth = async () => { | ||
try { | ||
const credentials = netrc.host(LOGIN_HOST); | ||
await axios.post(INFISICAL_URL + "/checkAuth", {}, { | ||
headers: { | ||
Authorization: "Bearer " + credentials.password | ||
} | ||
}); | ||
} catch (err) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
module.exports = { | ||
connectToWorkspace, | ||
checkConnect, | ||
getWorkspaceKeys, | ||
getSharedKey, | ||
uploadSecrets, | ||
getSecrets | ||
getSecrets, | ||
checkAuth | ||
}; |
@@ -5,3 +5,4 @@ const { | ||
PUSH, | ||
PULL | ||
PULL, | ||
NODE | ||
} = require('./variables'); | ||
@@ -12,2 +13,3 @@ const login = require('./actions/login'); | ||
const connect = require('./actions/connect'); | ||
const node = require('./actions/node'); | ||
@@ -50,3 +52,7 @@ /** | ||
default: | ||
console.log("❌ Error: Command not recognized"); | ||
// TODO: spawn child process + inject environment variables | ||
node({ | ||
args | ||
}); | ||
// console.log("❌ Error: Command not recognized"); | ||
return; | ||
@@ -53,0 +59,0 @@ } |
const netrc = require('netrc-rw'); | ||
const jsrp = require('jsrp'); | ||
const axios = require('axios'); | ||
const { | ||
decryptSymmetric | ||
} = require("./crypto"); | ||
const { | ||
INFISICAL_URL, | ||
LOGIN_HOST, | ||
KEYS_HOST | ||
} = require("../variables"); | ||
@@ -8,3 +16,3 @@ /** Return set of specified host credentials from | ||
* @param {Object} obj | ||
* @param {String} host - LOGIN_HOST or KEYS_HOST | ||
* @param {String} obj.host - LOGIN_HOST or KEYS_HOST | ||
*/ | ||
@@ -25,5 +33,108 @@ const getCredentials = ({ | ||
/** | ||
* Authenticate user with SRP | ||
* @param {Object} obj | ||
* @param {Object} obj.email - email | ||
* @param {Object} obj.password - password | ||
* @return {Boolean} success - whether or not user successfully authenticated | ||
e*/ | ||
const authenticate = async ({ | ||
email, | ||
password | ||
}) => { | ||
const promise = new Promise(function (resolve, reject) { | ||
const client = new jsrp.client(); | ||
client.init({ | ||
username: email, | ||
password, | ||
}, async () => { | ||
try { | ||
const clientPublicKey = client.getPublicKey(); | ||
let serverPublicKey, salt; | ||
let res = await axios.post(INFISICAL_URL + '/login1', { | ||
email, | ||
clientPublicKey | ||
}); | ||
serverPublicKey = res.data.serverPublicKey; | ||
salt = res.data.salt; | ||
client.setSalt(salt); | ||
client.setServerPublicKey(serverPublicKey); | ||
const clientProof = client.getProof(); // M1 | ||
res = await axios.post(INFISICAL_URL + '/login2', { | ||
email, | ||
clientProof | ||
}); | ||
// decrypt private key | ||
const privateKey = decryptSymmetric({ | ||
ciphertext: res.data.encryptedPrivateKey, | ||
iv: res.data.iv, | ||
tag: res.data.tag, | ||
key: password.slice(0, 32).padStart(32, '0') | ||
}); | ||
// update authentication information on file | ||
updateNetRC({ | ||
host: LOGIN_HOST, | ||
login: email, | ||
password: res.data.token | ||
}); | ||
// update key information on file | ||
updateNetRC({ | ||
host: KEYS_HOST, | ||
login: res.data.publicKey, | ||
password: privateKey | ||
}); | ||
resolve(); | ||
} catch (err) { | ||
reject("Failed to login"); | ||
} | ||
}); | ||
}); | ||
try { | ||
await promise; | ||
} catch (err) { | ||
throw new Error("❌ Error: Something went wrong while logging you in... Let's try that again"); | ||
} | ||
} | ||
/** | ||
* Overwrite NetRC file with new credentails. | ||
* @param {Object} obj | ||
* @param {String} obj.host - new host information | ||
* @param {String} obj.login - new username information | ||
* @param {String} obj.password - new password information | ||
*/ | ||
const updateNetRC = ({ | ||
host, | ||
login, | ||
password | ||
}) => { | ||
try { | ||
let credentials = netrc.host(host); | ||
// host exists | ||
netrc.host(host).login = login; | ||
netrc.host(host).password = password; | ||
netrc.write(); | ||
} catch (err) { | ||
// host doesn't exist | ||
netrc.addHost(host).password = password; | ||
netrc.write(); | ||
netrc.host(host).login = login; | ||
netrc.write(); | ||
} | ||
} | ||
module.exports = { | ||
getCredentials | ||
getCredentials, | ||
authenticate | ||
} | ||
@@ -7,2 +7,6 @@ const path = require('path'); | ||
} = require('../variables'); | ||
const { | ||
decryptAsymmetric, | ||
decryptSymmetric | ||
} = require("../utilities/crypto"); | ||
@@ -20,7 +24,3 @@ /** | ||
} catch (err) { | ||
console.error( | ||
"Error: Failed to read file " | ||
+ fileName | ||
); | ||
process.exit(1); | ||
throw new Error("❌ Failed to read from file " + fileName); | ||
} | ||
@@ -34,4 +34,5 @@ | ||
* exists in the folder at [currentPath] | ||
* @param {String} fileName - file name | ||
* @param {String} content - content to write to file | ||
* @param {Object} obj | ||
* @param {String} obj.fileName - file name | ||
* @param {String} obj.content - content to write to file | ||
*/ | ||
@@ -45,4 +46,3 @@ const write = ({ | ||
} catch (err) { | ||
console.error("Error: Failed to write to file " + fileName) | ||
process.exit(1); | ||
throw new Error("❌ Failed to write to file " + fileName); | ||
} | ||
@@ -97,3 +97,3 @@ } | ||
write, | ||
parse | ||
parse | ||
} |
@@ -7,2 +7,3 @@ #! /usr/bin/env node | ||
const PULL = "pull"; | ||
const NODE = "node"; | ||
@@ -26,2 +27,3 @@ // parsing | ||
PULL, | ||
NODE, | ||
LINE, | ||
@@ -28,0 +30,0 @@ INFISICAL_URL, |
{ | ||
"name": "infisical", | ||
"version": "1.0.19", | ||
"version": "1.0.20", | ||
"description": "Sync .env files simply, securely", | ||
@@ -29,3 +29,2 @@ "main": "index.js", | ||
"npm": "^8.16.0", | ||
"open": "^8.4.0", | ||
"prompt-sync": "^4.2.0", | ||
@@ -32,0 +31,0 @@ "tweetnacl": "^1.0.3", |
@@ -39,20 +39,2 @@ ## Infisical | ||
## Example | ||
``` | ||
npx infisical login | ||
``` | ||
``` | ||
npx infisical connect 12345a6b12354872f789101d1 | ||
``` | ||
``` | ||
npx infisical push dev | ||
``` | ||
``` | ||
npx infisical pull dev | ||
``` | ||
Voila! | ||
@@ -59,0 +41,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56812
9
18
1030
46
4
6
+ Addedcipher-base@1.0.6(transitive)
- Removedopen@^8.4.0
- Removedcipher-base@1.0.5(transitive)
- Removeddefine-lazy-prop@2.0.0(transitive)
- Removedis-docker@2.2.1(transitive)
- Removedis-wsl@2.2.0(transitive)
- Removedopen@8.4.2(transitive)