ice-client
Advanced tools
Comparing version 0.6.5 to 0.7.0
335
index.js
@@ -1,13 +0,10 @@ | ||
"use strict"; | ||
const AWS = require('aws-sdk'); | ||
const crypto = require('crypto'); | ||
var AWS = require("aws-sdk"); | ||
const Config = {}; | ||
exports.Config = {} | ||
exports.configure = function(keyId, secret, token, key, context) { | ||
var region = "us-east-1"; | ||
var ctx = {}; | ||
if (key != undefined) { | ||
var parts = key.split(":"); | ||
function configure(accessKeyId, secretAccessKey, sessionToken, key, context) { | ||
let region; | ||
if (key !== undefined) { | ||
const parts = key.split(':'); | ||
if (parts.length === 6) { | ||
@@ -18,152 +15,242 @@ region = parts[3]; | ||
exports.Config = { | ||
accessKeyId: keyId, | ||
secretAccessKey: secret, | ||
sessionToken: token, | ||
region: region, | ||
key: key, | ||
context: context, | ||
}; | ||
Config.accessKeyId = accessKeyId; | ||
Config.secretAccessKey = secretAccessKey; | ||
Config.sessionToken = sessionToken; | ||
Config.region = region; | ||
Config.key = key; | ||
Config.context = context; | ||
} | ||
exports.configureFromEnv = function(prefix) { | ||
if (prefix === undefined) { | ||
prefix = "ICE"; | ||
function encryptionContext() { | ||
const c = {}; | ||
if (Config.context !== undefined) { | ||
const parts = Config.context.split('='); | ||
if (parts.length === 2) { | ||
c[parts[0]] = parts[1]; | ||
} | ||
} | ||
exports.configure( | ||
process.env[prefix + "_AWS_ACCESS_KEY_ID"], | ||
process.env[prefix + "_AWS_SECRET_ACCESS_KEY"], | ||
process.env[prefix + "_AWS_SESSION_TOKEN"], | ||
process.env[prefix + "_KEY"], | ||
process.env[prefix + "_CONTEXT"] | ||
); | ||
return c; | ||
} | ||
exports.configureFromEnv(); | ||
function configureFromEnv(prefix) { | ||
const p = prefix || 'ICE'; | ||
exports.checkACL = function(cb) { | ||
var acl = { | ||
access: false, | ||
audit: false, | ||
} | ||
Config.level = prefix.toLowerCase(); | ||
configure( | ||
process.env[`${p}_AWS_ACCESS_KEY_ID`], | ||
process.env[`${p}_AWS_SECRET_ACCESS_KEY`], | ||
process.env[`${p}_AWS_SESSION_TOKEN`], | ||
process.env[`${p}_KEY`], | ||
process.env[`${p}_CONTEXT`]); | ||
} | ||
exports.CWL().filterLogEvents({limit: 1}, function(err, data) { | ||
if (!err) { | ||
acl.access = true; | ||
acl.audit = true; | ||
} | ||
function IAM() { | ||
return new AWS.IAM({ | ||
accessKeyId: Config.accessKeyId, | ||
region: Config.region, | ||
secretAccessKey: Config.secretAccessKey, | ||
sessionToken: Config.sessionToken, | ||
}); | ||
} | ||
switch(err && err.code) { | ||
case "UnrecognizedClientException": | ||
break; | ||
case "AccessDeniedException": | ||
acl.access = true; | ||
break; | ||
function getPolicy() { | ||
return IAM().getUser().promise() | ||
.then(resp => IAM().getUserPolicy({ | ||
UserName: resp.User.UserName, | ||
PolicyName: 'ICE', | ||
}).promise()) | ||
.catch((err) => { | ||
const m = err.message.match(/arn:aws:sts::[0-9]+:assumed-role\/([^ ]+)\/([^ ]+)/); | ||
if (m !== null) { | ||
return IAM().getRolePolicy({ | ||
RoleName: m[1], | ||
PolicyName: 'ICE', | ||
}).promise(); | ||
} | ||
cb(acl); | ||
}) | ||
return Promise.reject(err); | ||
}); | ||
} | ||
exports.KMS = function () { | ||
var c = {}; | ||
function getACL(cb) { | ||
const acl = { | ||
access: false, | ||
audit: false, | ||
data: false, | ||
decrypt: false, | ||
encrypt: false, | ||
}; | ||
var context = exports.Config.context; | ||
if (context) { | ||
var parts = context.split("="); | ||
if (parts.length === 2) { | ||
c[parts[0]] = parts[1]; | ||
} | ||
} | ||
return new Promise((resolve) => { | ||
getPolicy() | ||
.then((resp) => { | ||
const policy = JSON.parse(unescape(decodeURI(resp.PolicyDocument))); | ||
const actions = []; | ||
policy.Statement.forEach((s) => { | ||
actions.push(...s.Action); | ||
}); | ||
acl.access = true; | ||
acl.audit = actions.includes('logs:FilterLogEvents'); | ||
acl.data = actions.includes('kms:GenerateDataKey*'); | ||
acl.decrypt = actions.includes('kms:Decrypt'); | ||
acl.encrypt = actions.includes('kms:Encrypt'); | ||
if (cb) { return cb(undefined, acl); } | ||
return resolve(acl); | ||
}) | ||
.catch(() => resolve(acl)); | ||
}); | ||
} | ||
function KMS() { | ||
return new AWS.KMS({ | ||
accessKeyId: exports.Config.accessKeyId, | ||
secretAccessKey: exports.Config.secretAccessKey, | ||
sessionToken: exports.Config.sessionToken, | ||
region: exports.Config.region, | ||
params: { EncryptionContext: c } | ||
accessKeyId: Config.accessKeyId, | ||
region: Config.region, | ||
secretAccessKey: Config.secretAccessKey, | ||
sessionToken: Config.sessionToken, | ||
params: { | ||
EncryptionContext: encryptionContext(), | ||
KeyId: Config.key, | ||
}, | ||
}); | ||
}; | ||
exports.CWL = function () { | ||
var key = exports.Config.key || "/undefined"; | ||
return new AWS.CloudWatchLogs({ | ||
accessKeyId: exports.Config.accessKeyId, | ||
secretAccessKey: exports.Config.secretAccessKey, | ||
sessionToken: exports.Config.sessionToken, | ||
region: exports.Config.region, | ||
params: { | ||
filterPattern: '"' + exports.Config.context + '"', | ||
interleaved: true, | ||
logGroupName: key.split("/")[1], | ||
} | ||
}) | ||
} | ||
exports.encrypt = function(plaintext, cb) { | ||
var params = { | ||
KeyId: exports.Config.key, | ||
Plaintext: plaintext | ||
function encrypt(plaintext, cb) { | ||
const params = { | ||
Plaintext: plaintext, | ||
}; | ||
exports.KMS().encrypt(params, function(err, data) { | ||
if (err) { | ||
return cb(err, ""); | ||
} | ||
return cb(undefined, data.CiphertextBlob); | ||
return new Promise((resolve, reject) => { | ||
KMS().encrypt(params).promise() | ||
.then((resp) => { | ||
if (cb) { return cb(undefined, resp.CiphertextBlob); } | ||
return resolve(resp.CiphertextBlob); | ||
}) | ||
.catch((err) => { | ||
if (cb) { return cb(err); } | ||
return reject(err); | ||
}); | ||
}); | ||
}; | ||
} | ||
exports.decrypt = function(ciphertext, cb) { | ||
function decrypt(ciphertext, cb) { | ||
let cipher = ciphertext; | ||
if (!(ciphertext instanceof Buffer)) { | ||
ciphertext = Buffer.from(ciphertext, 'base64'); | ||
cipher = Buffer.from(ciphertext, 'base64'); | ||
} | ||
var params = { | ||
CiphertextBlob: ciphertext | ||
const params = { | ||
CiphertextBlob: cipher, | ||
}; | ||
exports.KMS().decrypt(params, function(err, data) { | ||
if (err) { | ||
return cb(err, ""); | ||
} | ||
return cb(undefined, data.Plaintext); | ||
return new Promise((resolve, reject) => { | ||
KMS().decrypt(params).promise() | ||
.then((resp) => { | ||
if (cb) { return cb(undefined, resp.Plaintext); } | ||
return resolve(resp.Plaintext); | ||
}) | ||
.catch((err) => { | ||
if (cb) { return cb(err); } | ||
return reject(err); | ||
}); | ||
}); | ||
}; | ||
} | ||
exports.audit = function(cb) { | ||
filterLogEvents(undefined, Date.now() - 24*60*60*1000, undefined, function(err, data) { | ||
cb(err, data) | ||
}) | ||
function encryptData(plaintext, cb) { | ||
const params = { | ||
KeySpec: 'AES_256', | ||
}; | ||
return new Promise((resolve, reject) => { | ||
KMS().generateDataKey(params).promise() | ||
.then((resp) => { | ||
const cipher = crypto.createCipher('aes256', resp.Plaintext); | ||
let ciphertext = cipher.update(plaintext, 'utf8', 'base64'); | ||
ciphertext += cipher.final('base64'); | ||
const cipherdata = { | ||
ciphertext: Buffer.from(ciphertext, 'base64'), | ||
key: resp.CiphertextBlob, | ||
}; | ||
if (cb) { return cb(undefined, cipherdata); } | ||
return resolve(cipherdata); | ||
}) | ||
.catch((err) => { | ||
if (cb) { return cb(err); } | ||
return reject(err); | ||
}); | ||
}); | ||
} | ||
function filterLogEvents(events, startTime, token, cb) { | ||
if (events === undefined) { | ||
events = [] | ||
} | ||
function decryptData(cipherdata, cb) { | ||
return new Promise((resolve, reject) => { | ||
decrypt(cipherdata.key) | ||
.then((plaintextKey) => { | ||
const decipher = crypto.createDecipher('aes256', plaintextKey); | ||
let plaintext = decipher.update(cipherdata.ciphertext, 'base64', 'utf8'); | ||
plaintext += decipher.final('utf8'); | ||
const p = Buffer.from(plaintext, 'utf8'); | ||
var params = { | ||
startTime: startTime | ||
} | ||
if (cb) { return cb(undefined, p); } | ||
return resolve(p); | ||
}) | ||
.catch((err) => { | ||
if (cb) { return cb(err); } | ||
return reject(err); | ||
}); | ||
}); | ||
} | ||
if (token !== undefined) { | ||
params.nextToken = token; | ||
function CWL() { | ||
const params = { | ||
interleaved: true, | ||
limit: 10, | ||
logGroupName: Config.key.split('/')[1], | ||
}; | ||
if (Config.context !== undefined && Config.context !== '') { | ||
params.filterPattern = `"${Config.context}"`; | ||
} | ||
exports.CWL().filterLogEvents(params, function(err, data) { | ||
if (err) { | ||
return cb(err, events); | ||
} | ||
return new AWS.CloudWatchLogs({ | ||
accessKeyId: Config.accessKeyId, | ||
region: Config.region, | ||
secretAccessKey: Config.secretAccessKey, | ||
sessionToken: Config.sessionToken, | ||
params, | ||
}); | ||
} | ||
for(var i = 0; i < data.events.length; i++) { | ||
events.unshift(JSON.parse(data.events[i].message)) | ||
} | ||
function audit(cb) { | ||
const params = { | ||
startTime: new Date().getTime() - (24 * 60 * 60 * 1000), | ||
}; | ||
if (data.nextToken === undefined) { | ||
return cb(undefined, events); | ||
} | ||
return new Promise((resolve, reject) => { | ||
CWL().filterLogEvents(params).promise() | ||
.then((resp) => { | ||
const logs = []; | ||
resp.events.forEach((e) => { | ||
logs.push(JSON.parse(e.message)); | ||
}); | ||
if (cb) { return cb(undefined, logs); } | ||
return resolve(logs); | ||
}) | ||
.catch((err) => { | ||
if (cb) { return cb(err); } | ||
return reject(err); | ||
}); | ||
}); | ||
} | ||
filterLogEvents(events, startTime, data.nextToken, cb); | ||
}) | ||
} | ||
exports.Config = Config; | ||
exports.audit = audit; | ||
exports.configure = configure; | ||
exports.configureFromEnv = configureFromEnv; | ||
exports.decrypt = decrypt; | ||
exports.decryptData = decryptData; | ||
exports.encrypt = encrypt; | ||
exports.encryptData = encryptData; | ||
exports.getACL = getACL; |
{ | ||
"name": "ice-client", | ||
"version": "0.6.5", | ||
"version": "0.7.0", | ||
"description": "Encrypt sensitive data at rest", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "mocha" | ||
"test": "ava && eslint *.js **/*.js" | ||
}, | ||
@@ -33,4 +33,6 @@ "repository": { | ||
"devDependencies": { | ||
"mocha": "^3.2.0" | ||
"ava": "^0.18.1", | ||
"dotenv": "^4.0.0", | ||
"eslint": "^3.15.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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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 8 instances 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
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 9 instances in 1 package
26125
21
556
14
3
1