Merge pull request #541 from Zagrios/chore/filter-sensitive-data-in-logs

[chore] filter sensitive data in logs
This commit is contained in:
MathieuG-P
2024-08-01 00:55:39 +02:00
committed by GitHub
5 changed files with 147 additions and 8 deletions
+129 -6
View File
@@ -23,16 +23,20 @@ import { LivShortcut } from "./services/liv/liv-shortcut.service";
import { SteamLauncherService } from "./services/bs-launcher/steam-launcher.service";
import { FileAssociationService } from "./services/file-association.service";
import { SongDetailsCacheService } from "./services/additional-content/maps/song-details-cache.service";
import { readdirSync, statSync, unlinkSync } from "fs-extra";
const isDebug = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true";
log.transports.file.level = "info";
log.transports.file.resolvePath = () => {
const now = new Date();
return path.join(app.getPath("logs"), `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}-v${app.getVersion()}.log`);
};
export const filterStrings = new Set<string>();
export const filterPatterns = new Set<RegExp>();
// Filter all occulus tokens
filterPatterns.add(/FRL\S{10,}/g);
initLogger();
deleteOlestLogs();
deleteOldLogs();
log.catchErrors();
if (process.env.NODE_ENV === "production") {
const sourceMapSupport = require("source-map-support");
@@ -128,5 +132,124 @@ if (!gotTheLock) {
log.error(args?.args);
});
ipcMain.on("add-filter-string", (_, args: IpcRequest<string>) => {
filterStrings.add(args?.args);
});
ipcMain.on("add-filter-pattern", (_, args: IpcRequest<string>) => {
filterPatterns.add(new RegExp(args?.args));
});
}).catch(log.error);
}
function initLogger(){
log.transports.file.level = "info";
log.transports.file.resolvePath = () => {
const now = new Date();
return path.join(app.getPath("logs"), `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}-v${app.getVersion()}.log`);
};
log.hooks.push((message) => {
const filterMessage = (filter: string|RegExp, ...param: unknown[]): unknown[] => {
return param.map(data => {
if(typeof data === "string"){
return data.replaceAll(filter, "****");
}
if(data instanceof Error){
data.message = data.message?.replaceAll(filter, "****");
data.stack = data.stack?.replaceAll(filter, "****");
}
if(data instanceof Array){
return filterMessage(filter, ...data);
}
return data;
});
}
filterStrings.forEach(filter => {
if(filter && message.data.length){
message.data = filterMessage(filter, ...message.data);
}
});
filterPatterns.forEach(filter => {
if(filter && message.data.length){
message.data = filterMessage(filter, ...message.data);
}
});
return message;
});
log.catchErrors();
}
function getLogFilesEntries() {
try {
const logsFolder = app.getPath("logs");
let logs = readdirSync(logsFolder, { withFileTypes: true });
logs = logs.filter(file => file.isFile() && path.extname(file.name) === ".log");
logs.sort((a, b) => {
const aStat = statSync(path.join(logsFolder, a.name));
const bStat = statSync(path.join(logsFolder, b.name));
return bStat.mtime.getTime() - aStat.mtime.getTime();
});
return logs.map(file => {
const filePath = path.join(logsFolder, file.name);
const stat = statSync(filePath);
return {
path: filePath,
name: file.name,
stats: stat
};
});
} catch (err) {
log.error('Error while retrieving log files entries:', err);
return [];
}
}
// keep only the last 5 logs
function deleteOldLogs(): void{
try {
let logs = getLogFilesEntries();
logs = logs.slice(5);
logs.forEach(file => {
try {
unlinkSync(file.path);
log.info(`Deleted log file: ${file.path}`);
} catch (err) {
log.error(`Error deleting file ${file.path}:`, err);
}
});
} catch (err) {
log.error("Error while deleting old logs:", err);
}
}
// Temporary function to delete logs before 2024-07-31
function deleteOlestLogs(): void{
// delete all logs before 2024-07-31
const date = new Date(2024, 6, 31); // month is 0-based
const logs = getLogFilesEntries().filter(file => file.stats.mtime.getTime() < date.getTime());
logs.forEach(file => {
try {
unlinkSync(file.path);
log.info(`Deleted log file: ${file.path}`);
} catch (err) {
log.error(`Error deleting file ${file.path}:`, err);
}
});
}
@@ -30,7 +30,7 @@ export const EnterMetaTokenModal: ModalComponent<string> = ({resolver}) => {
const cancel = () => {
resolver({exitCode: ModalExitCode.CANCELED});
}
return (
<form className="flex flex-col w-80 gap-4">
<h1 className="text-3xl uppercase tracking-wide w-full text-center">{t("modals.enter-meta-token.title")}</h1>
@@ -205,7 +205,7 @@ const PasswordInput = ({onChange, value}: {onChange: (value : {password: string,
<input className="grow px-1 py-[2px] outline-none bg-transparent" onChange={e => onChange({password: e.target.value, valid: isPasswordValid(e.target.value)})} value={value} type={showPassword ? "text" : "password"} name="password" id="password" placeholder={t("modals.enter-meta-token.body.password")} />
<BsmButton className="shrink-0 m-1 rounded-md p-0.5 !bg-light-main-color-3 dark:!bg-main-color-3" icon={showPassword ? "eye-cross" : "eye"} withBar={false} onClick={() => setShowPassword(prev => !prev)} />
</div>
</>
</>
)
}
+8
View File
@@ -62,4 +62,12 @@ export function logRenderError(...params: unknown[]){
ipc.sendLazy("log-error", { args: params });
}
export function addFilterStringLog(str: string){
ipc.sendLazy("add-filter-string", { args: str });
}
export function addFilterPatternLog(pattern: string){
ipc.sendLazy("add-filter-pattern", { args: pattern });
}
@@ -11,6 +11,7 @@ import { AbstractBsDownloaderService } from "./abstract-bs-downloader.service";
import { DownloadInfo } from "main/services/bs-version-download/bs-steam-downloader.service";
import { MetaAuthErrorCodes, OculusDownloaderErrorCodes } from "shared/models/bs-version-download/oculus-download.model";
import { EnterMetaTokenModal } from "renderer/components/modal/modal-types/bs-downgrade/enter-meta-token-modal.component";
import { addFilterStringLog } from "renderer";
export class OculusDownloaderService extends AbstractBsDownloaderService implements DownloaderServiceInterface{
@@ -88,6 +89,8 @@ export class OculusDownloaderService extends AbstractBsDownloaderService impleme
return false;
}
addFilterStringLog(tokenRes.data);
return lastValueFrom(this.startDownloadBsVersion({ bsVersion, isVerification, token: tokenRes.data })).then(() => true);
})().then(res => {
@@ -13,6 +13,7 @@ import { DepotDownloaderErrorEvent, DepotDownloaderEvent, DepotDownloaderEventTy
import { SteamMobileApproveModal } from "renderer/components/modal/modal-types/bs-downgrade/steam-mobile-approve-modal.component";
import { DownloaderServiceInterface } from "./bs-store-downloader.interface";
import { AbstractBsDownloaderService } from "./abstract-bs-downloader.service";
import { addFilterStringLog } from "renderer";
export class SteamDownloaderService extends AbstractBsDownloaderService implements DownloaderServiceInterface{
@@ -219,6 +220,10 @@ export class SteamDownloaderService extends AbstractBsDownloaderService implemen
return Promise.resolve();
}
if(loginRes?.data?.password){
addFilterStringLog(loginRes.data.password);
}
if(loginRes.data.stay){
this.setSteamSession(loginRes.data.username);
}