Feat/obscure sensitive bucket credentials (#375)

* obscure sensitive bucket credentials

* npm audit fix

* fix condition

* add test suite encrypt-decrypt.test

* revert docker-compose

* update pipeline

---------

Co-authored-by: mfrindt <m.frindt@cognigy.com>
This commit is contained in:
Markus Frindt
2025-01-03 13:12:44 +01:00
committed by GitHub
parent ce4618523c
commit 23cd4408a5
8 changed files with 315 additions and 35 deletions
+87 -5
View File
@@ -17,10 +17,15 @@ const encrypt = (text) => {
};
const decrypt = (data) => {
const hash = JSON.parse(data);
const decipher = crypto.createDecipheriv(algorithm, secretKey, Buffer.from(hash.iv, 'hex'));
const decrpyted = Buffer.concat([decipher.update(Buffer.from(hash.content, 'hex')), decipher.final()]);
return decrpyted.toString();
try {
const hash = JSON.parse(data);
const decipher = crypto.createDecipheriv(algorithm, secretKey, Buffer.from(hash.iv, 'hex'));
const decrpyted = Buffer.concat([decipher.update(Buffer.from(hash.content, 'hex')), decipher.final()]);
return decrpyted.toString();
} catch (error) {
console.error('Error while decrypting data', error);
return '{}';
}
};
const obscureKey = (key, key_spoiler_length = 6) => {
@@ -33,8 +38,85 @@ const obscureKey = (key, key_spoiler_length = 6) => {
return `${key.slice(0, key_spoiler_length)}${key_spoiler_char.repeat(key.length - key_spoiler_length)}`;
};
function isObscureKey(bucketCredentials) {
if (!bucketCredentials) {
return false;
}
try {
const {
vendor,
secret_access_key = '',
service_key = '',
connection_string = ''
} = bucketCredentials || {};
let pattern;
switch (vendor) {
case 'aws_s3':
case 's3_compatible':
pattern = /^([A-Za-z0-9]{4,6}X+$)/;
return pattern.test(secret_access_key);
case 'azure':
pattern = /^https:[A-Za-z0-9\/.:?=&_-]+$/;
return pattern.test(connection_string);
case 'google': {
pattern = /^([A-Za-z0-9]{4,6}X+$)/;
let {private_key} = JSON.parse(service_key);
const key_header = '-----BEGIN PRIVATE KEY-----\n';
private_key = private_key.slice(key_header.length, private_key.length);
return pattern.test(private_key || '');
}
}
return false;
} catch (error) {
console.log('Error in isObscureKey', error);
return false;
}
}
/**
* obscure sensitive data in bucket credentials
* an obscured key contains of 6 'spoiled' characters of the key followed by 'X' characters
* '123456XXXXXXXXXXXXXXXXXXXXXXXX'
* @param {*} obj
* @returns
*/
function obscureBucketCredentialsSensitiveData(obj) {
if (!obj) return obj;
const {vendor, service_key, connection_string, secret_access_key} = obj;
switch (vendor) {
case 'aws_s3':
case 's3_compatible':
obj.secret_access_key = obscureKey(secret_access_key);
break;
case 'google':
const o = JSON.parse(service_key);
let private_key = o.private_key;
if (!isObscureKey(obj)) {
const key_header = '-----BEGIN PRIVATE KEY-----\n';
private_key = o.private_key.slice(key_header.length, o.private_key.length);
private_key = `${key_header}${obscureKey(private_key)}`;
}
const obscured = {
...o,
private_key
};
obj.service_key = JSON.stringify(obscured);
break;
case 'azure':
obj.connection_string = obscureKey(connection_string);
break;
}
return obj;
}
module.exports = {
encrypt,
decrypt,
obscureKey
obscureKey,
isObscureKey,
obscureBucketCredentialsSensitiveData,
};