mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
|
/**
|
||
|
* A sanitizer interface that provides methods to sanitize log entries.
|
||
|
*/
|
||
|
interface ISanitizer {
|
||
|
/**
|
||
|
* Sanitizes the provided log entry. Should be called only if canSanitize returns true.
|
||
|
* @param {any} entry - The log entry to sanitize.
|
||
|
* @returns {any} The sanitized log entry.
|
||
|
*/
|
||
|
sanitize(entry: any): any;
|
||
|
|
||
|
/**
|
||
|
* Checks if the sanitizer can handle the given log entry.
|
||
|
* @param {any} entry - The log entry to check.
|
||
|
* @returns {boolean} True if the sanitizer can handle the log entry, false otherwise.
|
||
|
*/
|
||
|
canSanitize(entry: any): boolean;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A log sanitizer class that sanitizes logs to avoid leaking sensitive/private data.
|
||
|
* only the first applicable sanitizer (as determined by canSanitize) will be applied
|
||
|
* Currently, it is hardcoded to sanitize only logs from Redis rpush command.
|
||
|
*/
|
||
|
export class LogSanitizer {
|
||
|
private _sanitizers: ISanitizer[] = [
|
||
|
new RedisSanitizer(),
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* Sanitizes the provided log entry using a predefined set of sanitizers.
|
||
|
* @param {any} log - The log entry to sanitize.
|
||
|
* @returns {any} The sanitized log entry.
|
||
|
*/
|
||
|
public sanitize(log: any): any {
|
||
|
for (const sanitizer of this._sanitizers) {
|
||
|
if (sanitizer.canSanitize(log)) {
|
||
|
return sanitizer.sanitize(log);
|
||
|
}
|
||
|
}
|
||
|
return log;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A sanitizer implementation for Redis logs.
|
||
|
*/
|
||
|
class RedisSanitizer implements ISanitizer {
|
||
|
/**
|
||
|
* Sanitizes the Redis log entry by replacing sensitive data in the payload with "[sanitized]".
|
||
|
* @param {any} entry - The Redis log entry to sanitize.
|
||
|
* @returns {any} The sanitized Redis log entry.
|
||
|
*/
|
||
|
public sanitize(entry: any): any {
|
||
|
// REDIS log structure looks like this: the first arg is the name of the queue,
|
||
|
// and the rest are the data that was pushed to the queue. Therefore, we are omitting the first arg.
|
||
|
for (let i = 1; i < entry.args.length; i++) {
|
||
|
let arg = entry.args[i];
|
||
|
let parsedArg: any = null;
|
||
|
parsedArg = JSON.parse(arg);
|
||
|
if (parsedArg?.payload) {
|
||
|
parsedArg.payload = "[sanitized]";
|
||
|
}
|
||
|
arg = JSON.stringify(parsedArg);
|
||
|
entry.args[i] = arg;
|
||
|
}
|
||
|
return entry;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Checks if the given log entry corresponds to a Redis rpush command.
|
||
|
* @param {any} entry - The log entry to check.
|
||
|
* @returns {boolean} True if the log entry is a Redis rpush command, false otherwise.
|
||
|
*/
|
||
|
public canSanitize(entry: any): boolean {
|
||
|
// We are only interested in rpush commands
|
||
|
return (
|
||
|
typeof entry === "object" &&
|
||
|
entry.command?.toLowerCase() === "rpush".toLowerCase() &&
|
||
|
entry.args &&
|
||
|
Array.isArray(entry.args)
|
||
|
);
|
||
|
}
|
||
|
}
|